Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1749 debug trace call #1759

Closed
wants to merge 13 commits into from
3 changes: 3 additions & 0 deletions libethereum/Block.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ class Block {

// Information concerning ongoing transactions

/// Get the gas limit in this block.
u256 gasLimit() const { return m_currentBlock.gasLimit(); }

/// Get the remaining gas limit in this block.
u256 gasLimitRemaining() const { return m_currentBlock.gasLimit() - gasUsed(); }

Expand Down
66 changes: 48 additions & 18 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ h256 Client::importTransaction( Transaction const& _t ) {


ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, bytes const& _data,
u256 _gas, u256 _gasPrice,
u256 _gasLimit, u256 _gasPrice,
#ifdef HISTORIC_STATE
BlockNumber _blockNumber,
#endif
Expand All @@ -1246,17 +1246,20 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,
// historic state
try {
u256 nonce = historicBlock.mutableState().mutableHistoricState().getNonce( _from );
u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas;
// if the user did not specify transaction gas limit, we give transaction block gas
// limit of gas
u256 gasLimit = _gasLimit == Invalid256 ? historicBlock.gasLimit() : _gasLimit;
u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
Transaction t( _value, gasPrice, gas, _dest, _data, nonce );
Transaction t( _value, gasPrice, gasLimit, _dest, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainParams().chainID );
t.checkOutExternalGas( ~u256( 0 ) );
if ( _ff == FudgeFactor::Lenient ) {
historicBlock.mutableState().mutableHistoricState().addBalance(
_from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
}

// if we are in a call, we add to the balance of the account
// value needed for the call to guaranteed pass
// geth does a similar thing, we need to check whether it is fully compatible with
// geth
historicBlock.mutableState().mutableHistoricState().addBalance(
_from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
ret = historicBlock.executeHistoricCall( bc().lastBlockHashes(), t, nullptr, 0 );
} catch ( ... ) {
cwarn << boost::current_exception_diagnostic_information();
Expand All @@ -1271,9 +1274,11 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,
// TODO there can be race conditions between prev and next line!
State readStateForLock = temp.mutableState().createStateReadOnlyCopy();
u256 nonce = max< u256 >( temp.transactionsFrom( _from ), m_tq.maxNonce( _from ) );
u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas;
// if the user did not specify transaction gas limit, we give transaction block gas
// limit of gas
u256 gasLimit = _gasLimit == Invalid256 ? temp.gasLimit() : _gasLimit;
u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
Transaction t( _value, gasPrice, gas, _dest, _data, nonce );
Transaction t( _value, gasPrice, gasLimit, _dest, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainParams().chainID );
t.checkOutExternalGas( ~u256( 0 ) );
Expand All @@ -1294,22 +1299,47 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,


#ifdef HISTORIC_STATE
Json::Value Client::traceCall(
Transaction& _t, BlockNumber _blockNumber, std::shared_ptr< AlethStandardTrace > _tracer ) {
Block historicBlock = blockByNumber( _blockNumber );

Json::Value Client::traceCall( Address const& _from, u256 _value, Address _to, bytes const& _data,
u256 _gasLimit, u256 _gasPrice, BlockNumber _blockNumber,
Json::Value const& _jsonTraceConfig ) {
try {
_t.setNonce( historicBlock.mutableState().mutableHistoricState().getNonce( _t.from() ) );
_t.checkOutExternalGas( ~u256( 0 ) );
Block historicBlock = blockByNumber( _blockNumber );
auto nonce = historicBlock.mutableState().mutableHistoricState().getNonce( _from );
// if the user did not specify transaction gas limit, we give transaction block gas
// limit of gas
auto gasLimit = _gasLimit == Invalid256 ? historicBlock.gasLimit() : _gasLimit;

Transaction t = createTransactionForCallOrTraceCall(
_from, _value, _to, _data, gasLimit, _gasPrice, nonce );
historicBlock.mutableState().mutableHistoricState().addBalance(
_t.from(), ( u256 )( _t.gas() * _t.gasPrice() + _t.value() ) );
auto er = historicBlock.executeHistoricCall( bc().lastBlockHashes(), _t, _tracer, 0 );
return _tracer->getJSONResult();
_from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
auto traceOptions = TraceOptions::make( _jsonTraceConfig );
auto tracer = make_shared< AlethStandardTrace >( t, traceOptions, true );
auto er = historicBlock.executeHistoricCall( bc().lastBlockHashes(), t, tracer, 0 );
return tracer->getJSONResult();
} catch ( ... ) {
cwarn << boost::current_exception_diagnostic_information();
throw;
}
}


Transaction Client::createTransactionForCallOrTraceCall( const Address& _from, const u256& _value,
const Address& _to, const bytes& _data, const u256& _gasLimit, const u256& _gasPrice,
const u256& _nonce ) const {
auto gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
Transaction t( _value, gasPrice, _gasLimit, _to, _data, _nonce );
// if call or trace call request did not specify from address, zero address is used
auto from = _from ? _from : ZeroAddress;
t.forceSender( from );
t.forceChainId( chainParams().chainID );
// call and traceCall do not use PoW
t.checkOutExternalGas( ~u256( 0 ) );
return t;
}


Json::Value Client::traceBlock( BlockNumber _blockNumber, Json::Value const& _jsonTraceConfig ) {
Block previousBlock = blockByNumber( _blockNumber - 1 );
Block historicBlock = blockByNumber( _blockNumber );
Expand Down
7 changes: 5 additions & 2 deletions libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,12 @@ class Client : public ClientBase, protected Worker {
FudgeFactor _ff = FudgeFactor::Strict ) override;

#ifdef HISTORIC_STATE
Json::Value traceCall(
Transaction& _t, BlockNumber _blockNumber, std::shared_ptr< AlethStandardTrace > _tracer );
Json::Value traceCall( Address const& _from, u256 _value, Address _to, bytes const& _data,
u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, Json::Value const& _jsonTraceConfig );
Json::Value traceBlock( BlockNumber _blockNumber, Json::Value const& _jsonTraceConfig );
Transaction createTransactionForCallOrTraceCall( const Address& _from, const u256& _value,
const Address& _to, const bytes& _data, const u256& _gasLimit, const u256& _gasPrice,
const u256& nonce ) const;
#endif


Expand Down
2 changes: 1 addition & 1 deletion libhistoric/AlethStandardTrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ AlethStandardTrace::AlethStandardTrace(
m_options( _options ),
// if it is a call trace, the transaction does not have signature
// therefore, its hash should not include signature
m_txHash( _t.sha3(_isCall? dev::eth::WithoutSignature: dev::eth::WithSignature) ),
m_txHash( _t.sha3( _isCall ? dev::eth::WithoutSignature : dev::eth::WithSignature ) ),
m_lastOpRecord(
// the top function is executed at depth 0
// therefore it is called from depth -1
Expand Down
15 changes: 2 additions & 13 deletions libweb3jsonrpc/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,19 +241,8 @@ Json::Value Debug::debug_traceCall( Json::Value const&

TransactionSkeleton ts = toTransactionSkeleton( _call );

if ( !ts.from ) {
ts.from = Address();
}

u256 gas = ts.gas == Invalid256 ? m_eth.gasLimitRemaining() : ts.gas;
u256 gasPrice = ts.gasPrice == Invalid256 ? m_eth.gasBidPrice() : ts.gasPrice;

Transaction t( ts.value, gasPrice, gas, ts.to, ts.data, ts.nonce );
t.forceSender( ts.from );
t.forceChainId( m_eth.chainParams().chainID );
auto traceOptions = TraceOptions::make( _jsonTraceConfig );
auto tracer = make_shared< AlethStandardTrace >( t, traceOptions, true );
return m_eth.traceCall( t, bN, tracer );
return m_eth.traceCall(
ts.from, ts.value, ts.to, ts.data, ts.gas, ts.gasPrice, bN, _jsonTraceConfig );
} catch ( Exception const& _e ) {
BOOST_THROW_EXCEPTION( jsonrpc::JsonRpcException( _e.what() ) );
}
Expand Down
4 changes: 4 additions & 0 deletions test/historicstate/hardhat/contracts/Tracer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ contract Tracer {
bytes32 expectedHash = keccak256(bytes(input));
return expectedHash;
}

function getBalance() external view returns (uint256) {
return balance;
}
}
1 change: 1 addition & 0 deletions test/historicstate/hardhat/run_geth.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env python3
import subprocess
import time
from web3 import Web3, HTTPProvider
Expand Down
Loading
Loading