Esempio n. 1
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]),
        )
Esempio n. 2
0
def test_chain_builder_initialize_chain_default(chain_class):
    chain = pipe(
        chain_class,
        genesis(),
    )

    header = chain.get_canonical_head()
    assert header == chain.get_canonical_block_by_number(0).header

    assert header.parent_hash == constants.GENESIS_PARENT_HASH
    assert header.uncles_hash == constants.EMPTY_UNCLE_HASH
    assert header.coinbase == constants.GENESIS_COINBASE
    assert header.state_root == constants.BLANK_ROOT_HASH
    assert header.transaction_root == constants.BLANK_ROOT_HASH
    assert header.receipt_root == constants.BLANK_ROOT_HASH
    assert header.bloom == 0
    assert header.difficulty == 1
    assert header.block_number == constants.GENESIS_BLOCK_NUMBER
    assert header.gas_limit == constants.GENESIS_GAS_LIMIT
    assert header.gas_used == 0
    # account for runtime.  should run in less than few seconds and should be
    # effectively "now"
    assert abs(header.timestamp - time.time()) < 2
    assert header.extra_data == constants.GENESIS_EXTRA_DATA
    assert header.mix_hash == constants.GENESIS_MIX_HASH
    assert header.nonce == constants.GENESIS_NONCE
Esempio n. 3
0
def test_chain_builder_initialize_chain_with_params(chain_class):
    chain = pipe(chain_class, genesis(params={'difficulty': 12345}, ))

    header = chain.get_canonical_head()
    assert header == chain.get_canonical_block_by_number(0).header

    assert header.difficulty == 12345
Esempio n. 4
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
Esempio n. 5
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
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()
Esempio n. 7
0
def bob_chain():
    chain = build(
        MiningChain,
        latest_mainnet_at(0),
        disable_pow_check(),
        genesis(),
    )
    return chain
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)
Esempio n. 9
0
def test_chain_builder_initialize_chain_with_state_simple(chain_class):
    chain = pipe(chain_class, genesis(state=((ADDRESS_A, 'balance', 1), ), ))

    header = chain.get_canonical_head()
    assert header == chain.get_canonical_block_by_number(0).header

    assert header.state_root != constants.BLANK_ROOT_HASH

    state = chain.get_vm().state
    assert state.get_balance(ADDRESS_A) == 1
def mining_chain_params(funded_address):
    return (
        MiningChain,
        frontier_at(0),
        disable_pow_check,
        genesis(params={'gas_limit': 1000000},
                state={funded_address: {
                    'balance': to_wei(1000, 'ether')
                }}),
    )
Esempio n. 11
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
Esempio n. 12
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')
Esempio n. 13
0
def test_mining_tools_proof_of_work_mining(base_vm_class):
    vm_class = type(base_vm_class.__name__, (POWMiningMixin, base_vm_class),
                    {})

    class ChainClass(MiningChain):
        vm_configuration = ((0, vm_class), )

    chain = genesis(ChainClass)

    block = chain.mine_block()
    check_eccpow(block.header.parent_hash, block.header.mining_hash, 24, 3, 6)
Esempio n. 14
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
Esempio n. 15
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
Esempio n. 16
0
def test_chain_builder_initialize_chain_with_state_multiple(chain_class):
    chain = pipe(
        chain_class,
        genesis(state=((ADDRESS_A, 'balance', 1), (ADDRESS_B, 'balance',
                                                   2)), ))

    header = chain.get_canonical_head()
    assert header == chain.get_canonical_block_by_number(0).header

    assert header.state_root != constants.BLANK_ROOT_HASH

    account_db = chain.get_vm().state.account_db
    assert account_db.get_balance(ADDRESS_A) == 1
    assert account_db.get_balance(ADDRESS_B) == 2
Esempio n. 17
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
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_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)
Esempio n. 21
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')
Esempio n. 22
0
def test_chain_builder_initialize_chain_with_params_and_state(chain_class):
    chain = pipe(
        chain_class,
        genesis(
            params={'difficulty': 12345},
            state=((ADDRESS_A, 'balance', 1), ),
        ))

    header = chain.get_canonical_head()
    assert header == chain.get_canonical_block_by_number(0).header

    assert header.difficulty == 12345

    assert header.state_root != constants.BLANK_ROOT_HASH

    state = chain.get_vm().state
    assert state.get_balance(ADDRESS_A) == 1
def test_mining_tools_proof_of_work_mining(base_vm_class):
    vm_class = type(base_vm_class.__name__, (POWMiningMixin, base_vm_class),
                    {})

    class ChainClass(MiningChain):
        vm_configuration = ((0, vm_class), )

    chain = genesis(ChainClass)

    block = chain.mine_block()
    check_pow(
        block.number,
        block.header.mining_hash,
        block.header.mix_hash,
        block.header.nonce,
        block.header.difficulty,
    )
Esempio n. 24
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)

        # 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
Esempio n. 25
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),
    )
Esempio n. 26
0
def load_mining_chain(db, *chain_builder_fns):
    GENESIS_PARAMS = {
        'coinbase': ZERO_ADDRESS,
        'difficulty': 5,
        'gas_limit': 3141592,
        'timestamp': 1514764800,
    }

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

    chain_builder_fns = (latest_mainnet_at(0),) if not chain_builder_fns else chain_builder_fns

    return build(
        AsyncMiningChain,
        *chain_builder_fns,
        enable_pow_mining(),
        genesis(db=db, params=GENESIS_PARAMS, state=GENESIS_STATE),
    )
        genesis(params={'gas_limit': 1000000},
                state={funded_address: {
                    'balance': to_wei(1000, 'ether')
                }}),
    )


@pytest.fixture
def mining_chain(mining_chain_params):
    return build(*mining_chain_params)


REGULAR_CHAIN_PARAMS = (
    Chain,
    frontier_at(0),
    genesis(),
)


@pytest.fixture
def regular_chain():
    return build(*REGULAR_CHAIN_PARAMS)


def test_chain_builder_build_single_default_block(mining_chain):
    chain = build(
        mining_chain,
        mine_block(),
    )

    header = chain.get_canonical_head()