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_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
Exemplo n.º 3
0
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_build_mine_multiple_blocks(mining_chain):
    chain = build(
        mining_chain,
        mine_blocks(5),
    )

    header = chain.get_canonical_head()
    assert header.block_number == 5
def test_chain_builder_construct_chain_name():
    chain = build(
        MiningChain,
        name('ChainForTest'),
    )

    assert issubclass(chain, MiningChain)
    assert chain.__name__ == 'ChainForTest'
def test_chain_builder_without_any_mining_config():
    chain = build(
        MiningChain,
        frontier_at(0),
        genesis(),
    )
    with pytest.raises(ValidationError, match='mix hash mismatch'):
        chain.mine_block()
def test_chain_builder_build_single_default_block(mining_chain):
    chain = build(
        mining_chain,
        mine_block(),
    )

    header = chain.get_canonical_head()
    assert header.block_number == 1
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_import_blocks_many(mining_chain):
    temp_chain = build(
        mining_chain,
        copy(),
        mine_blocks(3),
    )
    block_1, block_2, block_3 = (
        temp_chain.get_canonical_block_by_number(1),
        temp_chain.get_canonical_block_by_number(2),
        temp_chain.get_canonical_block_by_number(3),
    )

    chain = build(
        mining_chain,
        import_blocks(block_1, block_2, block_3),
    )
    head = chain.get_canonical_head()
    assert head == block_3.header
def test_chain_builder_construct_chain_vm_configuration_single_fork():
    chain = build(
        MiningChain,
        fork_at(FrontierVM, 0),
    )

    assert issubclass(chain, MiningChain)
    assert len(chain.vm_configuration) == 1
    assert chain.vm_configuration[0][0] == 0
    assert chain.vm_configuration[0][1] == FrontierVM
def test_chain_builder_construct_chain_vm_configuration_multiple_forks():
    chain = build(
        MiningChain,
        fork_at(FrontierVM, 0),
        fork_at(HomesteadVM, 5),
    )

    assert issubclass(chain, MiningChain)
    assert len(chain.vm_configuration) == 2
    assert chain.vm_configuration[0][0] == 0
    assert chain.vm_configuration[0][1] == FrontierVM
    assert chain.vm_configuration[1][0] == 5
    assert chain.vm_configuration[1][1] == HomesteadVM
def test_chain_builder_enable_pow_mining():
    chain = build(
        MiningChain,
        frontier_at(0),
        enable_pow_mining(),
        genesis(),
    )
    block = chain.mine_block()
    check_pow(
        block.number,
        block.header.mining_hash,
        block.header.mix_hash,
        block.header.nonce,
        block.header.difficulty,
    )
def test_chain_builder_disable_pow_check():
    chain = build(
        MiningChain,
        frontier_at(0),
        disable_pow_check(),
        genesis(),
    )
    block = chain.mine_block()
    with pytest.raises(ValidationError, match='mix hash mismatch'):
        check_pow(
            block.number,
            block.header.mining_hash,
            block.header.mix_hash,
            block.header.nonce,
            block.header.difficulty,
        )
def test_chain_builder_construct_chain_fork_specific_helpers(
        fork_fn, vm_class):
    class DummyVM(FrontierVM):
        pass

    class ChainForTest(MiningChain):
        vm_configuration = ((0, DummyVM), )

    chain = build(
        ChainForTest,
        fork_fn(12),
    )

    assert issubclass(chain, MiningChain)
    assert len(chain.vm_configuration) == 2
    assert chain.vm_configuration[0][0] == 0
    assert chain.vm_configuration[0][1] is DummyVM
    assert chain.vm_configuration[1][0] == 12
    assert chain.vm_configuration[1][1] is vm_class
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 any_chain(request):
    return build(*request.param)
def regular_chain():
    return build(*REGULAR_CHAIN_PARAMS)
def mining_chain():
    return build(*MINING_CHAIN_PARAMS)