Skip to content

Instantly share code, notes, and snippets.

@dylanjw
Last active March 2, 2018 06:49
Show Gist options
  • Save dylanjw/9840c00cce16ad42167ccc488e2d9f89 to your computer and use it in GitHub Desktop.
Save dylanjw/9840c00cce16ad42167ccc488e2d9f89 to your computer and use it in GitHub Desktop.

original eth-tester estimate_gas:

421     def estimate_gas(self, transaction):
  1         # TODO: move this to the VM level (and use binary search approach)
  2         signed_evm_transaction = self._get_normalized_and_signed_evm_transaction(
  3             dict(transaction, gas=self._max_available_gas()),
  4         )
  5 
  6         computation = _execute_and_revert_transaction(self.chain, signed_evm_transaction, 'pending')
  7         if computation.is_error:
  8             raise TransactionFailed(str(computation._error))
  9 
 10         gas_used = computation.gas_meter.start_gas - computation.gas_meter.gas_remaining
 11 
 12         return int(max(gas_used * GAS_ESTIMATE_BUFFER, MINIMUM_GAS_ESTIMATE))

replacing with py-evm chain.estimate_gas().

    def estimate_gas(self, transaction):
        signed_evm_transaction = self._get_normalized_and_signed_evm_transaction(
            dict(transaction, gas=self._max_available_gas()),
            block_number='pending',
        )
        return self.chain.estimate_gas(signed_evm_transaction)
results in gas limit exceeded
tests/backends/test_pyevm.py::TestPyEVMBackendDirect::test_estimate_gas <- eth_tester/utils/backend_testing.py FAILED
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

self = <test_pyevm.TestPyEVMBackendDirect object at 0x7f653139c278>, eth_tester = <eth_tester.main.EthereumTester object at 0x7f65313992b0>

    def test_estimate_gas(self, eth_tester):
        self.skip_if_no_evm_execution()
    
        math_address = _deploy_math(eth_tester)
        estimate_call_math_transaction = _make_call_math_transaction(
            eth_tester,
            math_address,
            'increment',
        )
>       gas_estimation = eth_tester.estimate_gas(estimate_call_math_transaction)

estimate_call_math_transaction = {'data': '0xd09de08a', 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', 'gas': 500000, 'to': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b'}
eth_tester = <eth_tester.main.EthereumTester object at 0x7f65313992b0>
math_address = '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b'
self       = <test_pyevm.TestPyEVMBackendDirect object at 0x7f653139c278>

eth_tester/utils/backend_testing.py:645: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
eth_tester/main.py:445: in estimate_gas
    raw_gas_estimate = self.backend.estimate_gas(raw_transaction)
eth_tester/backends/pyevm/main.py:425: in estimate_gas
    return self.chain.estimate_gas(signed_evm_transaction)
venv/lib/python3.6/site-packages/evm/chains/chain.py:277: in estimate_gas
    return self.gas_estimator(state, transaction)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
venv/lib/python3.6/site-packages/evm/estimators/gas.py:59: in binary_gas_search
    error = _get_computation_error(state, maximum_transaction)
venv/lib/python3.6/site-packages/evm/estimators/gas.py:29: in _get_computation_error
    computation = state.execute_transaction(transaction)
venv/lib/python3.6/site-packages/evm/vm/forks/spurious_dragon/vm_state.py:22: in execute_transaction
    computation = _execute_frontier_transaction(self, transaction)
venv/lib/python3.6/site-packages/evm/vm/forks/frontier/vm_state.py:56: in _execute_frontier_transaction
    vm_state.validate_transaction(transaction)
venv/lib/python3.6/site-packages/evm/vm/forks/homestead/vm_state.py:13: in validate_transaction
    validate_homestead_transaction(self, transaction)
venv/lib/python3.6/site-packages/evm/vm/forks/homestead/validation.py:17: in validate_homestead_transaction
    validate_frontier_transaction(evm, transaction)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

vm_state = <evm.vm.forks.spurious_dragon.vm_state.SpuriousDragonVMState object at 0x7f6531396208>, transaction = <evm.utils.spoof.SpoofTransaction object at 0x7f65313b3be0>

    def validate_frontier_transaction(vm_state, transaction):
        gas_cost = transaction.gas * transaction.gas_price
        with vm_state.state_db(read_only=True) as state_db:
            sender_balance = state_db.get_balance(transaction.sender)
    
        if sender_balance < gas_cost:
            raise ValidationError(
                "Sender account balance cannot afford txn gas: `{0}`".format(transaction.sender)
            )
    
        total_cost = transaction.value + gas_cost
    
        if sender_balance < total_cost:
            raise ValidationError("Sender account balance cannot afford txn")
    
        if vm_state.gas_used + transaction.gas > vm_state.gas_limit:
>           raise ValidationError("Transaction exceeds gas limit")
E           evm.exceptions.ValidationError: Transaction exceeds gas limit

gas_cost   = 3144659
sender_balance = 999999999999999999799489
state_db   = <evm.db.state.AccountStateDB object at 0x7f653138e0b8>
total_cost = 3144659
transaction = <evm.utils.spoof.SpoofTransaction object at 0x7f65313b3be0>
vm_state   = <evm.vm.forks.spurious_dragon.vm_state.SpuriousDragonVMState object at 0x7f6531396208>

venv/lib/python3.6/site-packages/evm/vm/forks/frontier/validation.py:22: ValidationError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /home/dwilson/Develop/Projects/ethereum/eth-tester/venv/lib/python3.6/site-packages/evm/vm/forks/frontier/validation.py(22)validate_frontier_transaction()
-> raise ValidationError("Transaction exceeds gas limit")
(Pdb) vm_state.gas_used()
*** TypeError: 'int' object is not callable
(Pdb) vm_state.gas_used
200511
(Pdb) transaction.gas
3144659
(Pdb) vm_state.gas_limit
3144659
(Pdb) 

Navigating up the stack to where the temp block context manager is created, and see 200511 gas_used

[28] > /home/dwilson/Develop/Projects/ethereum/eth-tester/venv/lib/python3.6/site-packages/evm/chains/chain.py(277)estimate_gas()
-> return self.gas_estimator(state, transaction)
(Pdb++) list
272  	
273  	    def estimate_gas(self, transaction, at_header=None):
274  	        if at_header is None:
275  	            at_header = self.get_canonical_head()
276  	        with self.get_vm(at_header).state_in_temp_block() as state:
277  ->	            return self.gas_estimator(state, transaction)
278  	
279  	    def import_block(self, block, perform_validation=True):
280  	        """
281  	        Imports a complete block.
282  	        """
(Pdb++) state.gas_used
200511

set breakpoint in estimate_gas() and start with 200511 gas_used

421  	    def estimate_gas(self, transaction):
422  	        import pdb; pdb.set_trace()
423  ->	        signed_evm_transaction = self._get_normalized_and_signed_evm_transaction(
424  	            dict(transaction, gas=self._max_available_gas()),
425  	        )
426  	        return self.chain.estimate_gas(signed_evm_transaction)
427  	
428  	    def call(self, transaction, block_number="latest"):
(Pdb++) self.chain.get_vm(self.chain.get_canonical_head()).state.gas_used
200511

Set breakpoint at top of test_estimate_gas() and run py-evm backend test, step through and check gas_used

>>>>>>>>>>>>>>>>>>>>>>> PDB set_trace (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>>>
[50] > /home/dwilson/Develop/Projects/ethereum/eth-tester/eth_tester/utils/backend_testing.py(638)test_estimate_gas()
-> self.skip_if_no_evm_execution()
(Pdb++) eth_tester.backend.chain.get_vm(eth_tester.backend.chain.get_canonical_head()).state.gas_used
0
(Pdb++) list
633  	        assert result == (0,)
634  	        assert result_new == (1,)
635  	
636  	    def test_estimate_gas(self, eth_tester):
637  	        import pdb; pdb.set_trace()
638  ->	        self.skip_if_no_evm_execution()
639  	
640  	        math_address = _deploy_math(eth_tester)
641  	        estimate_call_math_transaction = _make_call_math_transaction(
642  	            eth_tester,
643  	            math_address,
(Pdb++) n
[50] > /home/dwilson/Develop/Projects/ethereum/eth-tester/eth_tester/utils/backend_testing.py(640)test_estimate_gas()
-> math_address = _deploy_math(eth_tester)
(Pdb++) n
[50] > /home/dwilson/Develop/Projects/ethereum/eth-tester/eth_tester/utils/backend_testing.py(641)test_estimate_gas()
-> estimate_call_math_transaction = _make_call_math_transaction(
(Pdb++) eth_tester.backend.chain.get_vm(eth_tester.backend.chain.get_canonical_head()).state.gas_used
200511
(Pdb++) list
636  	    def test_estimate_gas(self, eth_tester):
637  	        import pdb; pdb.set_trace()
638  	        self.skip_if_no_evm_execution()
639  	
640  	        math_address = _deploy_math(eth_tester)
641  ->	        estimate_call_math_transaction = _make_call_math_transaction(
642  	            eth_tester,
643  	            math_address,
644  	            'increment',
645  	        )
646  	        gas_estimation = eth_tester.estimate_gas(estimate_call_math_transaction)
(Pdb++) 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment