@@ -1734,7 +1734,156 @@ func (api *TraceAPIImpl) doCall(ctx context.Context, dbtx kv.Tx, stateReader sta
17341734}
17351735
17361736// RawTransaction implements trace_rawTransaction.
1737- func (api * TraceAPIImpl ) RawTransaction (ctx context.Context , txHash common.Hash , traceTypes []string ) ([]any , error ) {
1738- var stub []any
1739- return stub , fmt .Errorf (NotImplemented , "trace_rawTransaction" )
1737+ func (api * TraceAPIImpl ) RawTransaction (ctx context.Context , encodedTx hexutil.Bytes , traceTypes []string ) (* TraceCallResult , error ) {
1738+ txn , err := types .DecodeWrappedTransaction (encodedTx )
1739+ if err != nil {
1740+ return nil , err
1741+ }
1742+
1743+ dbtx , err := api .kv .BeginTemporalRo (ctx )
1744+ if err != nil {
1745+ return nil , err
1746+ }
1747+ defer dbtx .Rollback ()
1748+
1749+ chainConfig , err := api .chainConfig (ctx , dbtx )
1750+ if err != nil {
1751+ return nil , err
1752+ }
1753+ engine := api .engine ()
1754+
1755+ var num = rpc .LatestBlockNumber
1756+ blockNrOrHash := rpc.BlockNumberOrHash {BlockNumber : & num }
1757+
1758+ blockNumber , hash , latest , err := rpchelper .GetBlockNumber (ctx , blockNrOrHash , dbtx , api ._blockReader , api .filters )
1759+ if err != nil {
1760+ return nil , err
1761+ }
1762+
1763+ err = api .BaseAPI .checkPruneHistory (ctx , dbtx , blockNumber )
1764+ if err != nil {
1765+ return nil , err
1766+ }
1767+
1768+ header , err := api .headerByNumber (ctx , rpc .BlockNumber (blockNumber ), dbtx )
1769+ if err != nil {
1770+ return nil , err
1771+ }
1772+ if header == nil {
1773+ return nil , fmt .Errorf ("block %d(%x) not found" , blockNumber , hash )
1774+ }
1775+
1776+ err = rpchelper .CheckBlockExecuted (dbtx , blockNumber )
1777+ if err != nil {
1778+ return nil , err
1779+ }
1780+
1781+ stateReader , err := rpchelper .CreateStateReaderFromBlockNumber (ctx , dbtx , blockNumber , latest , 0 , api .stateCache , api ._txNumReader )
1782+ if err != nil {
1783+ return nil , err
1784+ }
1785+
1786+ ibs := state .New (stateReader )
1787+
1788+ var cancel context.CancelFunc
1789+ if api .evmCallTimeout > 0 {
1790+ ctx , cancel = context .WithTimeout (ctx , api .evmCallTimeout )
1791+ } else {
1792+ ctx , cancel = context .WithCancel (ctx )
1793+ }
1794+ defer cancel ()
1795+
1796+ traceResult := & TraceCallResult {Trace : []* ParityTrace {}}
1797+ var traceTypeTrace , traceTypeStateDiff , traceTypeVmTrace bool
1798+ for _ , traceType := range traceTypes {
1799+ switch traceType {
1800+ case TraceTypeTrace :
1801+ traceTypeTrace = true
1802+ case TraceTypeStateDiff :
1803+ traceTypeStateDiff = true
1804+ case TraceTypeVmTrace :
1805+ traceTypeVmTrace = true
1806+ default :
1807+ return nil , fmt .Errorf ("unrecognized trace type: %s" , traceType )
1808+ }
1809+ }
1810+ if traceTypeVmTrace {
1811+ traceResult .VmTrace = & VmTrace {Ops : []* VmTraceOp {}}
1812+ }
1813+
1814+ var ot OeTracer
1815+ ot .config , err = parseOeTracerConfig (nil )
1816+ if err != nil {
1817+ return nil , err
1818+ }
1819+ ot .compat = api .compatibility
1820+ if traceTypeTrace || traceTypeVmTrace || traceTypeStateDiff {
1821+ ot .r = traceResult
1822+ ot .traceAddr = []int {}
1823+ }
1824+
1825+ signer := types .MakeSigner (chainConfig , header .Number .Uint64 (), header .Time )
1826+ blockCtx := transactions .NewEVMBlockContext (engine , header , blockNrOrHash .RequireCanonical , dbtx , api ._blockReader , chainConfig )
1827+ rules := blockCtx .Rules (chainConfig )
1828+
1829+ msg , err := txn .AsMessage (* signer , header .BaseFee , rules )
1830+ if err != nil {
1831+ return nil , err
1832+ }
1833+ msg .SetCheckNonce (false )
1834+ msg .SetCheckTransaction (false )
1835+ msg .SetCheckGas (false )
1836+
1837+ txCtx := protocol .NewEVMTxContext (msg )
1838+
1839+ blockCtx .GasLimit = math .MaxUint64
1840+ blockCtx .MaxGasLimit = true
1841+
1842+ evm := vm .NewEVM (blockCtx , txCtx , ibs , chainConfig , vm.Config {Tracer : ot .Tracer ().Hooks })
1843+
1844+ go func () {
1845+ <- ctx .Done ()
1846+ evm .Cancel ()
1847+ }()
1848+
1849+ gp := new (protocol.GasPool ).AddGas (msg .Gas ()).AddBlobGas (msg .BlobGas ())
1850+ var execResult * evmtypes.ExecutionResult
1851+ ibs .SetTxContext (blockCtx .BlockNumber , 0 )
1852+ ibs .SetHooks (ot .Tracer ().Hooks )
1853+
1854+ if ot .Tracer () != nil && ot .Tracer ().Hooks .OnTxStart != nil {
1855+ ot .Tracer ().OnTxStart (evm .GetVMContext (), txn , msg .From ())
1856+ }
1857+ execResult , err = protocol .ApplyMessage (evm , msg , gp , true /* refunds */ , true /* gasBailout */ , engine )
1858+ if err != nil {
1859+ if ot .Tracer () != nil && ot .Tracer ().Hooks .OnTxEnd != nil {
1860+ ot .Tracer ().OnTxEnd (nil , err )
1861+ }
1862+ return nil , err
1863+ }
1864+ if ot .Tracer () != nil && ot .Tracer ().Hooks .OnTxEnd != nil {
1865+ ot .Tracer ().OnTxEnd (& types.Receipt {GasUsed : execResult .ReceiptGasUsed }, nil )
1866+ }
1867+
1868+ traceResult .Output = common .Copy (execResult .ReturnData )
1869+ if traceTypeStateDiff {
1870+ sdMap := make (map [accounts.Address ]* StateDiffAccount )
1871+ traceResult .StateDiff = sdMap
1872+ sd := & StateDiff {sdMap : sdMap }
1873+ if err = ibs .FinalizeTx (evm .ChainRules (), sd ); err != nil {
1874+ return nil , err
1875+ }
1876+ initialIbs := state .New (stateReader )
1877+ sd .CompareStates (initialIbs , ibs )
1878+ }
1879+
1880+ if evm .Cancelled () {
1881+ return nil , fmt .Errorf ("execution aborted (timeout = %v)" , api .evmCallTimeout )
1882+ }
1883+
1884+ if ! traceTypeTrace {
1885+ traceResult .Trace = []* ParityTrace {}
1886+ }
1887+
1888+ return traceResult , nil
17401889}
0 commit comments