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
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
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_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

    account_db = chain.get_vm().state.account_db
    assert account_db.get_balance(ADDRESS_A) == 1
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_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_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

    account_db = chain.get_vm().state.account_db
    assert account_db.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,
    )
    chain_split,
    copy,
    disable_pow_check,
    frontier_at,
    genesis,
    import_block,
    import_blocks,
    mine_block,
    mine_blocks,
)

MINING_CHAIN_PARAMS = (
    MiningChain,
    frontier_at(0),
    disable_pow_check,
    genesis(),
)


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


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