def test_apply_transaction( # noqa: F811 chain_without_block_validation, funded_address, funded_address_private_key): chain = chain_without_block_validation # noqa: F811 # Don't change these variables vm = chain.get_vm() chaindb = copy.deepcopy(vm.chaindb) block0 = copy.deepcopy(vm.block) prev_block_hash = chain.get_canonical_block_by_number(0).hash initial_state_root = vm.block.header.state_root # (1) Get VM.apply_transaction(transaction) result for assertion # The first transaction chain1 = copy.deepcopy(chain) vm_example = chain1.get_vm() recipient1 = decode_hex('0x1111111111111111111111111111111111111111') amount = 100 from_ = funded_address tx1 = new_transaction( vm_example, from_, recipient1, amount, private_key=funded_address_private_key, ) computation, result_block = vm_example.apply_transaction(tx1) # The second transaction recipient2 = decode_hex('0x2222222222222222222222222222222222222222') tx2 = new_transaction( vm_example, from_, recipient2, amount, private_key=funded_address_private_key, ) computation, result_block = vm_example.apply_transaction(tx2) assert len(result_block.transactions) == 2 # (2) Test State.apply_transaction(...) # Use SpuriousDragonState to apply transaction chaindb1 = copy.deepcopy(chaindb) block1 = copy.deepcopy(block0) prev_hashes = vm.get_prev_hashes( last_block_hash=prev_block_hash, db=vm.chaindb, ) execution_context = block1.header.create_execution_context(prev_hashes) state1 = SpuriousDragonState( chaindb=chaindb1, execution_context=execution_context, state_root=block1.header.state_root, receipts=[], ) parent_hash = copy.deepcopy(prev_hashes[0]) computation, block, _ = state1.apply_transaction( tx1, block1, ) access_logs1 = computation.state.access_logs # Check if prev_hashes hasn't been changed assert parent_hash == prev_hashes[0] # Make sure that block1 hasn't been changed assert block1.header.state_root == initial_state_root execution_context = block.header.create_execution_context(prev_hashes) state1 = SpuriousDragonState( chaindb=chaindb1, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.state.receipts, ) computation, block, _ = state1.apply_transaction( tx2, block, ) access_logs2 = computation.state.access_logs post_state = computation.state # Check AccessLogs witness_db = ChainDB(MemoryDB(access_logs2.writes)) state_db = witness_db.get_state_db(block.header.state_root, read_only=True) assert state_db.get_balance(recipient2) == amount with pytest.raises(KeyError): _ = state_db.get_balance(recipient1) # Check block data are correct assert block.header.state_root == result_block.header.state_root assert block.header.gas_limit == result_block.header.gas_limit assert block.header.gas_used == result_block.header.gas_used assert block.header.transaction_root == result_block.header.transaction_root assert block.header.receipt_root == result_block.header.receipt_root # Make sure that state1 hasn't been changed assert post_state.state_root == result_block.header.state_root # (3) Testing using witness as db data # Witness_db block2 = copy.deepcopy(block0) witness_db = ChainDB(MemoryDB(access_logs1.reads)) prev_hashes = vm.get_prev_hashes( last_block_hash=prev_block_hash, db=vm.chaindb, ) execution_context = block2.header.create_execution_context(prev_hashes) # Apply the first transaction state2 = SpuriousDragonState( chaindb=witness_db, execution_context=execution_context, state_root=block2.header.state_root, receipts=[], ) computation, block, _ = state2.apply_transaction( tx1, block2, ) # Update witness_db recent_trie_nodes = merge(access_logs2.reads, access_logs1.writes) witness_db = ChainDB(MemoryDB(recent_trie_nodes)) execution_context = block.header.create_execution_context(prev_hashes) # Apply the second transaction state2 = SpuriousDragonState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.state.receipts, ) computation, block, _ = state2.apply_transaction( tx2, block, ) # After applying assert block.header.state_root == computation.state.state_root assert block.header.transaction_root == result_block.header.transaction_root assert block.header.receipt_root == result_block.header.receipt_root assert block.hash == result_block.hash # (3) Testing using witness_db and block_header to reconstruct state prev_hashes = vm.get_prev_hashes( last_block_hash=prev_block_hash, db=vm.chaindb, ) execution_context = block.header.create_execution_context(prev_hashes) state3 = SpuriousDragonState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, ) assert state3.state_root == post_state.state_root assert state3.state_root == result_block.header.state_root
FrontierStateForTesting = FrontierState.configure( __name__='FrontierStateForTesting', get_ancestor_hash=get_block_hash_for_testing, ) HomesteadStateForTesting = HomesteadState.configure( __name__='HomesteadStateForTesting', get_ancestor_hash=get_block_hash_for_testing, ) TangerineWhistleStateForTesting = TangerineWhistleState.configure( __name__='TangerineWhistleStateForTesting', get_ancestor_hash=get_block_hash_for_testing, ) SpuriousDragonStateForTesting = SpuriousDragonState.configure( __name__='SpuriousDragonStateForTesting', get_ancestor_hash=get_block_hash_for_testing, ) ByzantiumStateForTesting = ByzantiumState.configure( __name__='ByzantiumStateForTesting', get_ancestor_hash=get_block_hash_for_testing, ) FrontierVMForTesting = FrontierVM.configure( __name__='FrontierVMForTesting', _state_class=FrontierStateForTesting, get_prev_hashes=get_prev_hashes_testing, ) HomesteadVMForTesting = HomesteadVM.configure( __name__='HomesteadVMForTesting', _state_class=HomesteadStateForTesting, get_prev_hashes=get_prev_hashes_testing,
def test_apply_transaction( chain_without_block_validation, funded_address, funded_address_private_key): chain = chain_without_block_validation # Don't change these variables vm = chain.get_vm() chaindb = copy.deepcopy(vm.chaindb) block0 = copy.deepcopy(vm.block) prev_block_hash = chain.get_canonical_block_by_number(0).hash initial_state_root = vm.block.header.state_root # (1) Get VM.apply_transaction(transaction) result for assertion # The first transaction chain1 = copy.deepcopy(chain) vm_example = chain1.get_vm() recipient1 = decode_hex('0x1111111111111111111111111111111111111111') amount = 100 from_ = funded_address tx1 = new_transaction( vm_example, from_, recipient1, amount, private_key=funded_address_private_key, ) computation, result_block = vm_example.apply_transaction(tx1) # The second transaction recipient2 = decode_hex('0x2222222222222222222222222222222222222222') tx2 = new_transaction( vm_example, from_, recipient2, amount, private_key=funded_address_private_key, ) computation, result_block = vm_example.apply_transaction(tx2) assert len(result_block.transactions) == 2 # (2) Test State.apply_transaction(...) # Use SpuriousDragonState to apply transaction chaindb1 = copy.deepcopy(chaindb) block1 = copy.deepcopy(block0) prev_hashes = vm.get_prev_hashes( last_block_hash=prev_block_hash, db=vm.chaindb, ) execution_context = block1.header.create_execution_context(prev_hashes) state1 = SpuriousDragonState( chaindb=chaindb1, execution_context=execution_context, state_root=block1.header.state_root, gas_used=0, ) parent_hash = copy.deepcopy(prev_hashes[0]) computation, block, _ = state1.apply_transaction( tx1, block1, ) # Check if prev_hashes hasn't been changed assert parent_hash == prev_hashes[0] # Make sure that block1 hasn't been changed assert block1.header.state_root == initial_state_root execution_context = block.header.create_execution_context(prev_hashes) state1 = SpuriousDragonState( chaindb=chaindb1, execution_context=execution_context, state_root=block.header.state_root, gas_used=computation.state.gas_used, ) computation, block, _ = state1.apply_transaction( tx2, block, ) post_state = computation.state # Check block data are correct assert block.header.state_root == result_block.header.state_root assert block.header.gas_limit == result_block.header.gas_limit assert block.header.gas_used == result_block.header.gas_used assert block.header.transaction_root == result_block.header.transaction_root assert block.header.receipt_root == result_block.header.receipt_root # Make sure that state1 hasn't been changed assert post_state.state_root == result_block.header.state_root