def setup_computation(vm_class, create_address, code): message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, create_address=create_address, value=0, data=b'', code=code, gas=1000000, ) tx_context = vm_class._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B, ) vm = vm_class(GENESIS_HEADER, ChainDB(AtomicDB())) computation = vm_class._state_class.computation_class( state=vm.state, message=message, transaction_context=tx_context, ) return computation
def prepare_computation(vm_class): message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, value=100, data=b'', code=b'', gas=800, ) tx_context = vm_class._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B, ) vm = vm_class(GENESIS_HEADER, ChainDB(MemoryDB())) computation = vm_class._state_class.computation_class( state=vm.state, message=message, transaction_context=tx_context, ) computation.state.account_db.touch_account( decode_hex(EMPTY_ADDRESS_IN_STATE)) computation.state.account_db.set_code(decode_hex(ADDRESS_WITH_CODE[0]), ADDRESS_WITH_CODE[1]) return computation
def setup_computation(VM, code): CANONICAL_ADDRESS_A = to_canonical_address("0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6") CANONICAL_ADDRESS_B = to_canonical_address("0xcd1722f3947def4cf144679da39c4c32bdc35681") message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, create_address=CANONICAL_ADDRESS_B, value=0, data=b'', code=code, gas=1000000, ) tx_context = VM._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B, ) computation =VM._state_class.computation_class( state=VM.state, message=message, transaction_context=tx_context, ) return computation
def build_evm_message(self, transaction: SignedTransactionAPI) -> MessageAPI: # Use vm_state.get_gas_price instead of transaction_context.gas_price so # that we can run get_transaction_result (aka~ eth_call) and estimate_gas. # Both work better if the GASPRICE opcode returns the original real price, # but the sender's balance doesn't actually deduct the gas. This get_gas_price() # will return 0 for eth_call, but transaction_context.gas_price will return # the same value as the GASPRICE opcode. gas_fee = transaction.gas * self.vm_state.get_gas_price(transaction) # Buy Gas self.vm_state.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.increment_nonce(transaction.sender) # Setup VM Message message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, self.vm_state.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.get_code(transaction.to) self.vm_state.logger.debug2( ( "TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | " "gas-price: %s | s: %s | r: %s | y_parity: %s | data-hash: %s" ), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.y_parity, encode_hex(keccak(transaction.data)), ) message = Message( gas=message_gas, to=transaction.to, sender=transaction.sender, value=transaction.value, data=data, code=code, create_address=contract_address, ) return message
def message(): message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, value=100, data=b'', code=b'', gas=100, ) return message
def message(canonical_address_a, canonical_address_b): message = Message( to=canonical_address_a, sender=canonical_address_b, value=100, data=b'', code=b'', gas=100, ) return message
def build_delegation_evm_message(self, transaction: SignedTransactionAPI) -> MessageAPI: ### DAEJUN changed ### # gas_fee = transaction.gas * transaction.gas_price gas_fee = 0 ### DAEJUN changed ### # Buy Gas self.vm_state.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.increment_nonce(transaction.sender) # Setup VM Message # VM에 최초로 전달하는 가스량. 그냥 두면 된다. message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, self.vm_state.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.get_code(transaction.to) self.vm_state.logger.debug2( ( "TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | " "gas-price: %s | s: %s | r: %s | y_parity: %s | data-hash: %s" ), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.y_parity, encode_hex(keccak(transaction.data)), ) message = Message( gas=message_gas, to=transaction.to, sender=transaction.sender, value=transaction.value, data=data, code=code, create_address=contract_address, ) return message
def prepare_child_message(self, gas: int, to: Address, value: int, data: BytesOrView, code: bytes, **kwargs: Any) -> MessageAPI: kwargs.setdefault('sender', self.msg.storage_address) child_message = Message(gas=gas, to=to, value=value, data=data, code=code, depth=self.msg.depth + 1, **kwargs) return child_message
def build_evm_message(self, transaction: BaseOrSpoofTransaction) -> Message: gas_fee = transaction.gas * transaction.gas_price # Buy Gas self.vm_state.account_db.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.account_db.increment_nonce(transaction.sender) # Setup VM Message message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, self.vm_state.account_db.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.account_db.get_code(transaction.to) self.vm_state.logger.debug2( ("TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | " "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.v, encode_hex(keccak(transaction.data)), ) message = Message( gas=message_gas, to=transaction.to, sender=transaction.sender, value=transaction.value, data=data, code=code, create_address=contract_address, ) return message
def _create_message(gas=1, to=ADDRESS_A, sender=ADDRESS_B, value=0, data=b"", code=b"", **kwargs): return Message(gas=gas, to=to, sender=sender, value=value, data=data, code=code, **kwargs)
def prepare_child_message(self, gas: int, to: Address, value: int, data: BytesOrView, code: bytes, **kwargs: Any) -> Message: """ Helper method for creating a child computation. """ kwargs.setdefault('sender', self.msg.storage_address) child_message = Message(gas=gas, to=to, value=value, data=data, code=code, depth=self.msg.depth + 1, **kwargs) return child_message
def test_is_origin_computation(computation, transaction_context): assert computation.is_origin_computation message2 = Message( to=CANONICAL_ADDRESS_A, # Different sender than the tx context origin sender=CANONICAL_ADDRESS_A, value=100, data=b'', code=b'', gas=100, ) computation2 = DummyComputation( state=None, message=message2, transaction_context=transaction_context, ) assert not computation2.is_origin_computation
def test_is_origin_computation(computation, transaction_context, canonical_address_a): assert computation.is_origin_computation message2 = Message( to=canonical_address_a, # Different sender than the tx context origin sender=canonical_address_a, value=100, data=b'', code=b'', gas=100, ) computation2 = DummyComputation( state=None, message=message2, transaction_context=transaction_context, ) assert not computation2.is_origin_computation
def fixture_to_computation(fixture, code, vm): message = Message( to=fixture['exec']['address'], sender=fixture['exec']['caller'], value=fixture['exec']['value'], data=fixture['exec']['data'], code=code, gas=fixture['exec']['gas'], ) transaction_context = BaseTransactionContext( origin=fixture['exec']['origin'], gas_price=fixture['exec']['gasPrice'], ) return vm.state.get_computation(message, transaction_context).apply_computation( vm.state, message, transaction_context, )
def gen_context(chain): CANONICAL_ADDRESS_A = to_canonical_address( "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6") CANONICAL_ADDRESS_B = to_canonical_address( "0xcd1722f3947def4cf144679da39c4c32bdc35681") state = chain.get_vm().state message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, create_address=None, value=0, data=b'', code=b'', gas=1000000, ) tx_context = chain.get_vm()._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B) return state, message, tx_context
def run_computation(vm, create_address, code, gas=1000000, to=CANONICAL_ADDRESS_A, transaction_sender=b'\x11' * 20, data=b'', access_list=None): executor = vm.state.get_transaction_executor() message = Message( to=to, sender=CANONICAL_ADDRESS_B, create_address=create_address, value=0, data=data, code=code, gas=gas, ) if access_list is not None: txn_builder = vm.get_transaction_builder() unsigned_transaction = txn_builder.new_unsigned_access_list_transaction( vm.chain_context.chain_id, nonce=2, gas_price=1, gas=gas, to=to, value=3, data=data, access_list=access_list, ) else: unsigned_transaction = vm.create_unsigned_transaction( nonce=2, gas_price=1, gas=gas, to=to, value=3, data=data, ) transaction = SpoofTransaction(unsigned_transaction, from_=transaction_sender) return executor.build_computation(message, transaction)
def execute_bytecode( self, origin, gas_price, gas, to, sender, value, data, code, code_address=None, ): """ Execute raw bytecode in the context of the current state of the virtual machine. """ if origin is None: origin = sender # Construct a message message = Message( gas=gas, to=to, sender=sender, value=value, data=data, code=code, code_address=code_address, ) # Construction a tx context transaction_context = self.state.get_transaction_context_class()( gas_price=gas_price, origin=origin, ) # Execute it in the VM return self.state.get_computation( message, transaction_context).apply_computation( self.state, message, transaction_context, )
def execute_bytecode( self, origin: Address, gas_price: int, gas: int, to: Address, sender: Address, value: int, data: bytes, code: bytes, code_address: Address = None, ) -> ComputationAPI: if origin is None: origin = sender # Construct a message message = Message( gas=gas, to=to, sender=sender, value=value, data=data, code=code, code_address=code_address, ) # Construction a tx context transaction_context = self.state.get_transaction_context_class()( gas_price=gas_price, origin=origin, ) # Execute it in the VM return self.state.get_computation( message, transaction_context).apply_computation( self.state, message, transaction_context, )
def prepare_computation(vm_class): message = Message( to=CANONICAL_ADDRESS_A, sender=CANONICAL_ADDRESS_B, value=100, data=b'', code=b'', gas=800, ) tx_context = vm_class._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B, ) computation = vm_class._state_class.computation_class( state=None, message=message, transaction_context=tx_context, ) return computation
def setup_computation(vm_class, create_address, code, chain_id=None, gas=1000000, to=CANONICAL_ADDRESS_A, data=b''): message = Message( to=to, sender=CANONICAL_ADDRESS_B, create_address=create_address, value=0, data=data, code=code, gas=gas, ) chain_context = ChainContext(chain_id) tx_context = vm_class._state_class.transaction_context_class( gas_price=1, origin=CANONICAL_ADDRESS_B, ) db = AtomicDB() vm = vm_class(GENESIS_HEADER, ChainDB(db), chain_context, ConsensusContext(db)) computation = vm_class._state_class.computation_class( state=vm.state, message=message, transaction_context=tx_context, ) return computation
vm = chain.get_vm() geometry_options = { "landscape": True, "margin": "0.5in", "headheight": "20pt", "headsep": "10pt", "includeheadfoot": True } doc = "" message = Message( supergas, MOCK_ADDRESS, MOCK_ADDRESS, 0, b'', bytecode, create_address=MOCK_ADDRESS, code_address=MOCK_ADDRESS, should_transfer_value=False ) vm.get_state_class() doc, comp = apply_latex_computation(vm,message) md = markdown.markdown(doc,extensions=['mdx_math','markdown.extensions.extra'],output_format="html5") md = md.replace("<script type=\"math/tex; mode=display\">","") print("""<!DOCTYPE html><html><head><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script> <style> th, td { border-bottom: 1px solid #ddd; padding: 10px;
def test_vm_fixtures(fixture, vm_class, computation_getter): chaindb = ChainDB(get_db_backend()) header = BlockHeader( coinbase=fixture['env']['currentCoinbase'], difficulty=fixture['env']['currentDifficulty'], block_number=fixture['env']['currentNumber'], gas_limit=fixture['env']['currentGasLimit'], timestamp=fixture['env']['currentTimestamp'], ) vm = vm_class(header=header, chaindb=chaindb) state = vm.state setup_state(fixture['pre'], state) code = state.get_code(fixture['exec']['address']) # Update state_root manually vm._block = vm.get_block().copy(header=vm.get_header().copy( state_root=state.state_root)) message = Message( to=fixture['exec']['address'], sender=fixture['exec']['caller'], value=fixture['exec']['value'], data=fixture['exec']['data'], code=code, gas=fixture['exec']['gas'], ) transaction_context = BaseTransactionContext( origin=fixture['exec']['origin'], gas_price=fixture['exec']['gasPrice'], ) computation = vm.state.get_computation( message, transaction_context).apply_computation( vm.state, message, transaction_context, ) # Update state_root manually vm._block = vm.get_block().copy( header=vm.get_header().copy(state_root=computation.state.state_root), ) if 'post' in fixture: # # Success checks # assert not computation.is_error log_entries = computation.get_log_entries() if 'logs' in fixture: actual_logs_hash = hash_log_entries(log_entries) expected_logs_hash = fixture['logs'] assert expected_logs_hash == actual_logs_hash elif log_entries: raise AssertionError("Got log entries: {0}".format(log_entries)) expected_output = fixture['out'] assert computation.output == expected_output gas_meter = computation._gas_meter expected_gas_remaining = fixture['gas'] actual_gas_remaining = gas_meter.gas_remaining gas_delta = actual_gas_remaining - expected_gas_remaining assert gas_delta == 0, "Gas difference: {0}".format(gas_delta) call_creates = fixture.get('callcreates', []) assert len(computation.children) == len(call_creates) call_creates = fixture.get('callcreates', []) for child_computation, created_call in zip(computation.children, call_creates): to_address = created_call['destination'] data = created_call['data'] gas_limit = created_call['gasLimit'] value = created_call['value'] assert child_computation.msg.to == to_address assert data == child_computation.msg.data or child_computation.msg.code assert gas_limit == child_computation.msg.gas assert value == child_computation.msg.value expected_account_db = fixture['post'] else: # # Error checks # assert computation.is_error assert isinstance(computation._error, VMError) expected_account_db = fixture['pre'] verify_state(expected_account_db, vm.state)
def test_vm_fixtures(fixture, vm_class, computation_getter): db = get_db_backend() chaindb = ChainDB(db) consensus_context = ConsensusContext(db) header = BlockHeader( coinbase=fixture['env']['currentCoinbase'], difficulty=fixture['env']['currentDifficulty'], block_number=fixture['env']['currentNumber'], gas_limit=fixture['env']['currentGasLimit'], timestamp=fixture['env']['currentTimestamp'], ) # None of the VM tests (currently) test chain ID, so the setting doesn't matter here. # When they *do* start testing ID, they will have to supply it as part of the environment. # For now, just hard-code it to something not used in practice: chain_context = ChainContext(chain_id=0) vm = vm_class(header=header, chaindb=chaindb, chain_context=chain_context, consensus_context=consensus_context) state = vm.state setup_state(fixture['pre'], state) code = state.get_code(fixture['exec']['address']) # Update state_root manually vm._block = vm.get_block().copy(header=vm.get_header().copy( state_root=state.state_root)) message = Message( to=fixture['exec']['address'], sender=fixture['exec']['caller'], value=fixture['exec']['value'], data=fixture['exec']['data'], code=code, gas=fixture['exec']['gas'], ) transaction_context = BaseTransactionContext( origin=fixture['exec']['origin'], gas_price=fixture['exec']['gasPrice'], ) computation = vm.state.get_computation( message, transaction_context).apply_computation( vm.state, message, transaction_context, ) # Update state_root manually vm._block = vm.get_block().copy( header=vm.get_header().copy(state_root=computation.state.state_root), ) if 'post' in fixture: # # Success checks # assert not computation.is_error log_entries = computation.get_log_entries() if 'logs' in fixture: actual_logs_hash = hash_log_entries(log_entries) expected_logs_hash = fixture['logs'] assert expected_logs_hash == actual_logs_hash elif log_entries: raise AssertionError(f"Got log entries: {log_entries}") expected_output = fixture['out'] assert computation.output == expected_output gas_meter = computation._gas_meter expected_gas_remaining = fixture['gas'] actual_gas_remaining = gas_meter.gas_remaining gas_delta = actual_gas_remaining - expected_gas_remaining assert gas_delta == 0, f"Gas difference: {gas_delta}" call_creates = fixture.get('callcreates', []) assert len(computation.children) == len(call_creates) call_creates = fixture.get('callcreates', []) for child_computation, created_call in zip(computation.children, call_creates): to_address = created_call['destination'] data = created_call['data'] gas_limit = created_call['gasLimit'] value = created_call['value'] assert child_computation.msg.to == to_address assert data == child_computation.msg.data or child_computation.msg.code assert gas_limit == child_computation.msg.gas assert value == child_computation.msg.value expected_account_db = fixture['post'] else: # # Error checks # assert computation.is_error assert isinstance(computation._error, VMError) expected_account_db = fixture['pre'] verify_state(expected_account_db, vm.state)