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 VMState.apply_transaction(...) # Use SpuriousDragonVMState 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) vm_state1 = SpuriousDragonVMState( chaindb=chaindb1, execution_context=execution_context, state_root=block1.header.state_root, receipts=[], ) parent_hash = copy.deepcopy(prev_hashes[0]) computation, block, _ = vm_state1.apply_transaction( tx1, block1, ) access_logs1 = computation.vm_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) vm_state1 = SpuriousDragonVMState( chaindb=chaindb1, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.vm_state.receipts, ) computation, block, _ = vm_state1.apply_transaction( tx2, block, ) access_logs2 = computation.vm_state.access_logs post_vm_state = computation.vm_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 vm_state1 hasn't been changed assert post_vm_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 vm_state2 = SpuriousDragonVMState( chaindb=witness_db, execution_context=execution_context, state_root=block2.header.state_root, receipts=[], ) computation, block, _ = vm_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 vm_state2 = SpuriousDragonVMState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.vm_state.receipts, ) computation, block, _ = vm_state2.apply_transaction( tx2, block, ) # After applying assert block.header.state_root == computation.vm_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 vm_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) vm_state3 = SpuriousDragonVMState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, ) assert vm_state3.state_root == post_vm_state.state_root assert vm_state3.state_root == result_block.header.state_root
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 VMState.apply_transaction(...) # Use FrontierVMState 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 = ExecutionContext.from_block_header(block1.header, prev_hashes) vm_state1 = FrontierVMState( chaindb=chaindb1, execution_context=execution_context, state_root=block1.header.state_root, receipts=[], ) parent_hash = copy.deepcopy(prev_hashes[0]) computation, block, _ = vm_state1.apply_transaction( tx1, block1, ) access_logs1 = computation.vm_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 = ExecutionContext.from_block_header(block.header, prev_hashes) vm_state1 = FrontierVMState( chaindb=chaindb1, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.vm_state.receipts, ) computation, block, _ = vm_state1.apply_transaction( tx2, block, ) access_logs2 = computation.vm_state.access_logs post_vm_state = computation.vm_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 vm_state1 hasn't been changed assert post_vm_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 = ExecutionContext.from_block_header(block2.header, prev_hashes) # Apply the first transaction vm_state2 = FrontierVMState( chaindb=witness_db, execution_context=execution_context, state_root=block2.header.state_root, receipts=[], ) computation, block, _ = vm_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 = ExecutionContext.from_block_header(block.header, prev_hashes) # Apply the second transaction vm_state2 = FrontierVMState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, receipts=computation.vm_state.receipts, ) computation, block, _ = vm_state2.apply_transaction( tx2, block, ) # After applying assert block.header.state_root == computation.vm_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 vm_state prev_hashes = vm.get_prev_hashes( last_block_hash=prev_block_hash, db=vm.chaindb, ) execution_context = ExecutionContext.from_block_header(block.header, prev_hashes) vm_state3 = FrontierVMState( chaindb=witness_db, execution_context=execution_context, state_root=block.header.state_root, ) assert vm_state3.state_root == post_vm_state.state_root assert vm_state3.state_root == result_block.header.state_root
def test_create_block(chain): # (1) Empty block. # block = vm.mine_block() block0 = chain.import_block(chain.get_vm().block) initial_state_root = block0.header.state_root # (2) Use VM.apply_transaction to get the witness data chain1 = copy.deepcopy(chain) vm1 = chain1.get_vm() # The first transaction vm = chain.get_vm() recipient1 = decode_hex('0x1111111111111111111111111111111111111111') amount = 100 from_ = chain.funded_address tx1 = new_transaction(vm1, from_, recipient1, amount, chain.funded_address_private_key) # Get the witness of tx1 computation, _ = vm1.apply_transaction(tx1) transaction_witness1 = computation.vm_state.access_logs.reads # The second transaction recipient2 = decode_hex('0x2222222222222222222222222222222222222222') tx2 = new_transaction(vm1, from_, recipient2, amount, chain.funded_address_private_key) # Get the witness of tx2 computation, block = vm1.apply_transaction(tx2) transaction_witness2 = computation.vm_state.access_logs.reads # Check AccessLogs witness_db = ChainDB(MemoryDB(computation.vm_state.access_logs.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) # Create a block and import to chain coinbase = decode_hex('0x3333333333333333333333333333333333333333') vm1.block.header.coinbase = coinbase assert len(vm1.block.transactions) == 2 block1 = chain1.import_block(vm1.block) # Check the block vm1 = chain1.get_vm() assert block1.header.coinbase == coinbase assert len(block1.transactions) == 2 assert len(block1.get_receipts(vm1.chaindb)) == 2 with vm1.state.state_db(read_only=True) as state_db1: assert state_db1.root_hash == block1.header.state_root # (3) Try to create a block by witnesses vm2 = copy.deepcopy(vm) transaction_packages = [ (tx1, transaction_witness1), (tx2, transaction_witness2), ] prev_hashes = vm2.get_prev_hashes( last_block_hash=block0.hash, db=vm2.chaindb, ) parent_header = block0.header # Create a block block2 = vm2.create_block( transaction_packages=transaction_packages, prev_hashes=prev_hashes, coinbase=coinbase, parent_header=parent_header, ) # Check the block assert len(block2.transactions) == 2 assert block2.header.block_number == 2 assert block2.header.coinbase == coinbase # Check if block2 == block1 assert block2.hash == block1.hash # Check if the given parameters are changed assert block0.header.state_root == initial_state_root assert block0.header.block_number == 1