def test_chain_builder_build_uncle_fork(mining_chain):
    chain = build(
        mining_chain,
        mine_block(),  # 1
        mine_block(),  # 2
    )

    fork_chain = build(
        chain,
        at_block_number(1),
        mine_block(extra_data=b'fork-it!'),  # fork 2
    )

    # we don't use canonical head here because the fork chain is non-canonical.
    uncle = fork_chain.get_block_header_by_hash(fork_chain.header.parent_hash)
    assert uncle.block_number == 2
    assert uncle != chain.get_canonical_head()

    chain = build(
        chain,
        mine_block(uncles=[uncle]),  # 3
    )

    header = chain.get_canonical_head()
    block = chain.get_block_by_hash(header.hash)
    assert len(block.uncles) == 1
    assert block.uncles[0] == uncle
def test_chain_builder_build_two_default_blocks(mining_chain):
    chain = build(
        mining_chain,
        mine_block(),
        mine_block(),
    )

    header = chain.get_canonical_head()
    assert header.block_number == 2
def test_rewards(vm_fn, miner_1_balance, miner_2_balance):

    OTHER_MINER_ADDRESS = 20 * b'\x01'
    TOTAL_BLOCKS_CANONICAL_CHAIN = 3

    chain = build(
        MiningChain,
        vm_fn(0),
        disable_pow_check(),
        genesis(),
        mine_block(),  # 1
        mine_block(),  # 2
    )

    fork_chain = build(
        chain,
        at_block_number(1),
        mine_block(extra_data=b'fork-it!',
                   coinbase=OTHER_MINER_ADDRESS),  # fork 2
    )

    # we don't use canonical head here because the fork chain is non-canonical.
    uncle = fork_chain.get_block_header_by_hash(fork_chain.header.parent_hash)
    assert uncle.block_number == 2
    assert uncle != chain.get_canonical_head()

    chain = build(
        chain,
        mine_block(uncles=[uncle]),  # 3
    )

    header = chain.get_canonical_head()
    block = chain.get_block_by_hash(header.hash)
    assert len(block.uncles) == 1
    assert block.uncles[0] == uncle

    vm = chain.get_vm()
    coinbase_balance = vm.state.account_db.get_balance(block.header.coinbase)
    other_miner_balance = vm.state.account_db.get_balance(uncle.coinbase)

    # We first test if the balance matches what we would determine
    # if we made all the API calls involved ourselves.
    assert coinbase_balance == (
        vm.get_block_reward() * TOTAL_BLOCKS_CANONICAL_CHAIN +
        vm.get_nephew_reward())
    assert other_miner_balance == vm.get_uncle_reward(block.number, uncle)

    # But we also ensure the balance matches the numbers that we calculated on paper
    assert coinbase_balance == to_wei(miner_1_balance, 'ether')
    assert other_miner_balance == to_wei(miner_2_balance, 'ether')
def test_chain_builder_mine_block_with_parameters(mining_chain):
    chain = build(
        mining_chain,
        mine_block(extra_data=b'test-setting-extra-data'),
    )

    header = chain.get_canonical_head()
    assert header.extra_data == b'test-setting-extra-data'
def test_chain_builder_chain_split(mining_chain):
    chain_a, chain_b = build(
        mining_chain,
        chain_split(
            (mine_block(extra_data=b'chain-a'), mine_block()),
            (mine_block(extra_data=b'chain-b'), mine_block(), mine_block()),
        ),
    )

    first_a = chain_a.get_canonical_block_by_number(1).header
    first_b = chain_b.get_canonical_block_by_number(1).header

    assert first_a.extra_data == b'chain-a'
    assert first_b.extra_data == b'chain-b'

    head_a = chain_a.get_canonical_head()
    assert head_a.block_number == 2

    head_b = chain_b.get_canonical_head()
    assert head_b.block_number == 3
def test_chain_builder_at_block_number(mining_chain):
    pre_fork_chain = build(
        mining_chain,
        mine_block(),  # 1
        mine_block(),  # 2
        mine_block(),  # 3
    )
    block_1 = pre_fork_chain.get_canonical_block_by_number(1)
    block_2 = pre_fork_chain.get_canonical_block_by_number(2)
    block_3 = pre_fork_chain.get_canonical_block_by_number(3)

    chain = build(
        pre_fork_chain,
        at_block_number(2),
        mine_block(extra_data=b'fork-it!'),  # fork 3
        mine_block(),  # fork 4
        mine_block(),  # fork 5
    )

    # ensure that our chain is ahead of the pre_fork_chain
    head = chain.get_canonical_head()
    assert head.block_number == 5

    pre_fork_head = pre_fork_chain.get_canonical_head()
    assert pre_fork_head.block_number == 3

    f_block_1 = chain.get_canonical_block_by_number(1)
    f_block_2 = chain.get_canonical_block_by_number(2)
    f_block_3 = chain.get_canonical_block_by_number(3)

    # verify that the fork diverges from the pre_fork_chain
    assert f_block_1 == block_1
    assert f_block_2 == block_2
    assert f_block_3 != block_3
def test_chain_builder_mine_block_only_on_mining_chain(regular_chain):
    with pytest.raises(ValidationError, match="MiningChain"):
        mine_block()(regular_chain)