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
예제 #2
0
def test_uncle_block_inclusion_validity(vm_fn):
    # This test ensures that a forked block which is behind by
    # more than 6 layers cannot act as an ancestor to the current block

    OTHER_MINER_ADDRESS = 20 * b'\x01'

    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

    with pytest.raises(ValidationError):
        chain = build(
            chain,
            # Mines blocks from 3 to 8 (both numbers inclusive)
            mine_blocks(6),
            # Mine block 9 with uncle
            mine_block(uncles=[uncle]),
        )
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
예제 #4
0
def test_rewards_nephew_uncle_different_vm(vm_fn_uncle, vm_fn_nephew,
                                           miner_1_balance, miner_2_balance):
    OTHER_MINER_ADDRESS = 20 * b'\x01'
    TOTAL_BLOCKS_CANONICAL_CHAIN = 10
    VM_CHANGE_BLOCK_NUMBER = 4

    chain = build(
        MiningChain,
        vm_fn_uncle(0),
        vm_fn_nephew(VM_CHANGE_BLOCK_NUMBER),
        disable_pow_check(),
        genesis(),
        mine_blocks(TOTAL_BLOCKS_CANONICAL_CHAIN - 1),
    )

    fork_chain = build(
        chain,
        at_block_number(3),
        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 == 4

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

    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.get_balance(block.header.coinbase)
    other_miner_balance = vm.state.get_balance(uncle.coinbase)

    uncle_vm = chain.get_vm_class_for_block_number(0)
    nephew_vm = chain.get_vm_class_for_block_number(VM_CHANGE_BLOCK_NUMBER)

    # We first test if the balance matches what we would determine
    # if we made all the API calls involved ourselves.
    assert coinbase_balance == (uncle_vm.get_block_reward() * 3 +
                                nephew_vm.get_block_reward() *
                                (TOTAL_BLOCKS_CANONICAL_CHAIN - 3) +
                                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')
예제 #5
0
    def _create(cls, model_class: Type[AsyncHeaderDB], *args: Any,
                **kwargs: Any) -> AsyncHeaderDB:
        headerdb = model_class(*args, **kwargs)
        from eth.chains.base import Chain
        from eth.tools.builder.chain import build, latest_mainnet_at, genesis

        build(
            Chain,
            latest_mainnet_at(0),
            genesis(db=headerdb.db),
        )
        return headerdb
예제 #6
0
    def _create(cls, model_class: Type[AsyncHeaderDB], *args: Any,
                **kwargs: Any) -> AsyncHeaderDB:
        from eth.chains.base import Chain
        from eth.tools.builder.chain import build, latest_mainnet_at, genesis

        genesis_params = kwargs.pop('genesis_params', None)

        headerdb = model_class(*args, **kwargs)

        build(
            Chain,
            latest_mainnet_at(0),
            genesis(db=headerdb.db, params=genesis_params),
        )
        return headerdb
예제 #7
0
def test_eip1559_txn_rewards(max_total_price, max_priority_price,
                             expected_miner_tips, funded_address,
                             funded_address_private_key):

    chain = build(
        MiningChain,
        berlin_at(0),
        london_at(1),  # Start London at block one to get easy 1gwei base fee
        disable_pow_check(),
        genesis(
            params=dict(gas_limit=10**7),
            state={funded_address: dict(balance=10**20)},
        ),
    )
    vm = chain.get_vm()
    txn = new_dynamic_fee_transaction(
        vm,
        from_=funded_address,
        to=funded_address,
        private_key=funded_address_private_key,
        max_priority_fee_per_gas=max_priority_price,
        max_fee_per_gas=max_total_price,
    )

    MINER = b'\x0f' * 20
    original_balance = vm.state.get_balance(MINER)
    chain.mine_all([txn], coinbase=MINER)
    new_balance = chain.get_vm().state.get_balance(MINER)

    BLOCK_REWARD = 2 * (10**18)
    assert original_balance + BLOCK_REWARD + expected_miner_tips == new_balance
예제 #8
0
def get_chain(vm: Type[BaseVM], genesis_state: GenesisState) -> MiningChain:

    chain = build(MiningChain, fork_at(vm, constants.GENESIS_BLOCK_NUMBER),
                  disable_pow_check(),
                  genesis(params=GENESIS_PARAMS, state=genesis_state))

    return chain
예제 #9
0
def test_rewards_uncle_created_at_different_generations(
        vm_fn, fork_at_block_number, miner_1_balance, miner_2_balance):
    OTHER_MINER_ADDRESS = 20 * b'\x01'
    TOTAL_BLOCKS_CANONICAL_CHAIN = 10

    chain = build(
        MiningChain,
        vm_fn(0),
        disable_pow_check(),
        genesis(),
        mine_blocks(TOTAL_BLOCKS_CANONICAL_CHAIN - 1),
    )

    fork_chain = build(
        chain,
        at_block_number(fork_at_block_number),
        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 == fork_at_block_number + 1

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

    header = chain.get_canonical_head()
    block = chain.get_block_by_hash(header.hash)

    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')
예제 #10
0
def bob_chain():
    chain = build(
        MiningChain,
        latest_mainnet_at(0),
        disable_pow_check(),
        genesis(),
    )
    return chain
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'
예제 #12
0
def test_chain_builder_construct_chain_name():
    chain = build(
        MiningChain,
        name('ChainForTest'),
    )

    assert issubclass(chain, MiningChain)
    assert chain.__name__ == 'ChainForTest'
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_build_mine_multiple_blocks(mining_chain):
    chain = build(
        mining_chain,
        mine_blocks(5),
    )

    header = chain.get_canonical_head()
    assert header.block_number == 5
예제 #15
0
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()
예제 #16
0
파일: db.py 프로젝트: wschwab/trinity
    def _create(cls, model_class: Type[AsyncHeaderDB], *args: Any,
                **kwargs: Any) -> AsyncHeaderDB:
        from eth.chains.base import Chain
        from eth.tools.builder.chain import build, latest_mainnet_at, genesis

        genesis_params = kwargs.pop('genesis_params', None)

        headerdb = model_class(*args, **kwargs)

        # SIDE EFFECT!
        # This uses the side effect of initializing a chain using the `builder`
        # tool to populate the genesis state into the database.
        build(
            Chain,
            latest_mainnet_at(0),
            genesis(db=headerdb.db, params=genesis_params),
        )
        return headerdb
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
예제 #18
0
def test_chain_builder_enable_pow_mining():
    chain = build(
        MiningChain,
        frontier_at(0),
        enable_pow_mining(),
        genesis(),
    )
    block = chain.mine_block()
    check_eccpow(block.header.parent_hash, block.header.mining_hash, 24, 3, 6)
예제 #19
0
def alice_chain(bob_chain):
    bob_genesis = bob_chain.headerdb.get_canonical_block_header_by_number(0)

    chain = build(
        MiningChain,
        latest_mainnet_at(0),
        disable_pow_check(),
        genesis(params={"timestamp": bob_genesis.timestamp}),
    )
    return chain
예제 #20
0
async def test_handshake_with_incompatible_fork_id(alice_chain, bob_chain):

    alice_chain = build(alice_chain, mine_block())

    pair_factory = ETHPeerPairFactory(alice_peer_context=ChainContextFactory(
        headerdb=AsyncHeaderDB(alice_chain.headerdb.db),
        vm_configuration=((1, PetersburgVM), (2, MuirGlacierVM))), )
    with pytest.raises(WrongForkIDFailure):
        async with pair_factory as (alice, bob):
            pass
예제 #21
0
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
예제 #22
0
def get_chain(vm: Type[VirtualMachineAPI],
              genesis_state: GenesisState) -> Iterable[MiningChain]:

    with tempfile.TemporaryDirectory() as temp_dir:
        level_db_obj = LevelDB(Path(temp_dir))
        level_db_chain = build(
            MiningChain, fork_at(vm, constants.GENESIS_BLOCK_NUMBER),
            disable_pow_check(),
            genesis(db=level_db_obj,
                    params=GENESIS_PARAMS,
                    state=genesis_state))
        yield level_db_chain
예제 #23
0
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
예제 #24
0
async def test_eth_api_head_info_updates_with_announce(alice, bob,
                                                       common_base_chain,
                                                       LESAPI_class):
    # bob mines two blocks on his chain
    got_announce = asyncio.Event()

    async def _handle_announce(connection, msg):
        got_announce.set()

    alice.connection.add_command_handler(Announce, _handle_announce)

    bob_genesis = common_base_chain.headerdb.get_canonical_block_header_by_number(
        0)

    assert alice.connection.has_logic(LESAPI_class.name)

    les_api = alice.connection.get_logic(LESAPI_class.name, LESAPI_class)

    assert les_api.head_info.head_hash == bob_genesis.hash
    assert les_api.head_info.head_td == bob_genesis.difficulty
    assert les_api.head_info.head_number == 0

    bob_chain = build(
        common_base_chain,
        mine_block(),
        mine_block(),
    )
    head = bob_chain.get_canonical_head()

    les_proto = bob.les_api.protocol
    assert isinstance(les_proto, BaseLESProtocol)
    assert head.block_number == 2
    total_difficulty = bob_chain.headerdb.get_score(head.hash)
    les_proto.send(
        Announce(
            AnnouncePayload(
                head_hash=head.hash,
                head_number=head.block_number,
                head_td=total_difficulty,
                reorg_depth=0,
                params=(),
            )))

    await asyncio.wait_for(got_announce.wait(), timeout=1)
    await asyncio.sleep(0.1)

    assert les_api.head_info.head_hash == head.hash
    assert les_api.head_info.head_td == total_difficulty
    assert les_api.head_info.head_number == 2
예제 #25
0
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,
    )
예제 #26
0
def test_chain_builder_disable_pow_check():
    chain = build(
        MiningChain,
        frontier_at(0),
        disable_pow_check(),
        genesis(),
    )
    block = chain.mine_block()
    # check_eccpow(
    #     block.header.parent_hash,
    #     block.header.mining_hash,
    #     24, 3, 6)
    with pytest.raises(ValidationError, match='mix hash mismatch'):
        # ToDo: Have to change difficulty
        check_eccpow(block.header.parent_hash, block.header.mining_hash, 24, 3,
                     6)
예제 #27
0
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_mine_block_with_transactions(
        mining_chain, funded_address, funded_address_private_key):
    tx = new_transaction(
        mining_chain.get_vm(),
        from_=funded_address,
        to=ZERO_ADDRESS,
        private_key=funded_address_private_key,
    )

    chain = build(
        mining_chain,
        mine_block(transactions=[tx]),
    )

    block = chain.get_canonical_block_by_number(1)
    assert len(block.transactions) == 1
    assert block.transactions[0] == tx
예제 #29
0
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
예제 #30
0
def load_mining_chain(db):
    GENESIS_PARAMS = {
        'coinbase': constants.ZERO_ADDRESS,
        'difficulty': 5,
        'gas_limit': 3141592,
        'timestamp': 1514764800,
    }

    GENESIS_STATE = {
        FUNDED_ACCT.public_key.to_canonical_address(): {
            "balance": 100000000000000000,
        }
    }

    return build(
        FakeAsyncChain,
        byzantium_at(0),
        enable_pow_mining(),
        genesis(db=db, params=GENESIS_PARAMS, state=GENESIS_STATE),
    )