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