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_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_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')
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')
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_mine_multiple_blocks_only_on_mining_chain( regular_chain): with pytest.raises(ValidationError, match="MiningChain"): mine_blocks(5)(regular_chain)