api.go 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. // Copyright 2021 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package tracers
  17. import (
  18. "bufio"
  19. "bytes"
  20. "context"
  21. "errors"
  22. "fmt"
  23. "io/ioutil"
  24. "os"
  25. "runtime"
  26. "sync"
  27. "time"
  28. "github.com/ethereum/go-ethereum/common"
  29. "github.com/ethereum/go-ethereum/common/hexutil"
  30. "github.com/ethereum/go-ethereum/consensus"
  31. "github.com/ethereum/go-ethereum/core"
  32. "github.com/ethereum/go-ethereum/core/mps"
  33. "github.com/ethereum/go-ethereum/core/rawdb"
  34. "github.com/ethereum/go-ethereum/core/state"
  35. "github.com/ethereum/go-ethereum/core/types"
  36. "github.com/ethereum/go-ethereum/core/vm"
  37. "github.com/ethereum/go-ethereum/ethdb"
  38. "github.com/ethereum/go-ethereum/internal/ethapi"
  39. "github.com/ethereum/go-ethereum/log"
  40. "github.com/ethereum/go-ethereum/params"
  41. "github.com/ethereum/go-ethereum/private"
  42. "github.com/ethereum/go-ethereum/rlp"
  43. "github.com/ethereum/go-ethereum/rpc"
  44. )
  45. const (
  46. // defaultTraceTimeout is the amount of time a single transaction can execute
  47. // by default before being forcefully aborted.
  48. defaultTraceTimeout = 5 * time.Second
  49. // defaultTraceReexec is the number of blocks the tracer is willing to go back
  50. // and reexecute to produce missing historical state necessary to run a specific
  51. // trace.
  52. defaultTraceReexec = uint64(128)
  53. )
  54. // Backend interface provides the common API services (that are provided by
  55. // both full and light clients) with access to necessary functions.
  56. type Backend interface {
  57. HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
  58. HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
  59. BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
  60. BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
  61. GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
  62. RPCGasCap() uint64
  63. ChainConfig() *params.ChainConfig
  64. Engine() consensus.Engine
  65. ChainDb() ethdb.Database
  66. StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, mps.PrivateStateRepository, error)
  67. StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, *state.StateDB, mps.PrivateStateRepository, error)
  68. // Quorum
  69. GetBlockchain() *core.BlockChain
  70. }
  71. // API is the collection of tracing APIs exposed over the private debugging endpoint.
  72. type API struct {
  73. backend Backend
  74. }
  75. // NewAPI creates a new API definition for the tracing methods of the Ethereum service.
  76. func NewAPI(backend Backend) *API {
  77. return &API{backend: backend}
  78. }
  79. type chainContext struct {
  80. api *API
  81. ctx context.Context
  82. }
  83. var _ core.ChainContext = &chainContext{}
  84. func (context *chainContext) Engine() consensus.Engine {
  85. return context.api.backend.Engine()
  86. }
  87. func (context *chainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
  88. header, err := context.api.backend.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
  89. if err != nil {
  90. return nil
  91. }
  92. if header.Hash() == hash {
  93. return header
  94. }
  95. header, err = context.api.backend.HeaderByHash(context.ctx, hash)
  96. if err != nil {
  97. return nil
  98. }
  99. return header
  100. }
  101. // Quorum
  102. func (context *chainContext) Config() *params.ChainConfig {
  103. return context.api.backend.ChainConfig()
  104. }
  105. func (context *chainContext) QuorumConfig() *core.QuorumChainConfig {
  106. return &core.QuorumChainConfig{}
  107. }
  108. func (context *chainContext) PrivateStateManager() mps.PrivateStateManager {
  109. return context.api.backend.GetBlockchain().PrivateStateManager()
  110. }
  111. func (context *chainContext) CheckAndSetPrivateState(txLogs []*types.Log, privateState *state.StateDB, psi types.PrivateStateIdentifier) {
  112. }
  113. // End Quorum
  114. // chainContext construts the context reader which is used by the evm for reading
  115. // the necessary chain context.
  116. func (api *API) chainContext(ctx context.Context) core.ChainContext {
  117. return &chainContext{api: api, ctx: ctx}
  118. }
  119. // blockByNumber is the wrapper of the chain access function offered by the backend.
  120. // It will return an error if the block is not found.
  121. func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
  122. block, err := api.backend.BlockByNumber(ctx, number)
  123. if err != nil {
  124. return nil, err
  125. }
  126. if block == nil {
  127. return nil, fmt.Errorf("block #%d not found", number)
  128. }
  129. return block, nil
  130. }
  131. // blockByHash is the wrapper of the chain access function offered by the backend.
  132. // It will return an error if the block is not found.
  133. func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
  134. block, err := api.backend.BlockByHash(ctx, hash)
  135. if err != nil {
  136. return nil, err
  137. }
  138. if block == nil {
  139. return nil, fmt.Errorf("block %s not found", hash.Hex())
  140. }
  141. return block, nil
  142. }
  143. // blockByNumberAndHash is the wrapper of the chain access function offered by
  144. // the backend. It will return an error if the block is not found.
  145. //
  146. // Note this function is friendly for the light client which can only retrieve the
  147. // historical(before the CHT) header/block by number.
  148. func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, error) {
  149. block, err := api.blockByNumber(ctx, number)
  150. if err != nil {
  151. return nil, err
  152. }
  153. if block.Hash() == hash {
  154. return block, nil
  155. }
  156. return api.blockByHash(ctx, hash)
  157. }
  158. // TraceConfig holds extra parameters to trace functions.
  159. type TraceConfig struct {
  160. *vm.LogConfig
  161. Tracer *string
  162. Timeout *string
  163. Reexec *uint64
  164. }
  165. // TraceCallConfig is the config for traceCall API. It holds one more
  166. // field to override the state for tracing.
  167. type TraceCallConfig struct {
  168. *vm.LogConfig
  169. Tracer *string
  170. Timeout *string
  171. Reexec *uint64
  172. StateOverrides *ethapi.StateOverride
  173. }
  174. // StdTraceConfig holds extra parameters to standard-json trace functions.
  175. type StdTraceConfig struct {
  176. vm.LogConfig
  177. Reexec *uint64
  178. TxHash common.Hash
  179. }
  180. // txTraceContext is the contextual infos about a transaction before it gets run.
  181. type txTraceContext struct {
  182. index int // Index of the transaction within the block
  183. hash common.Hash // Hash of the transaction
  184. block common.Hash // Hash of the block containing the transaction
  185. // Quorum
  186. tx *types.Transaction // Transaction is needed
  187. }
  188. // txTraceResult is the result of a single transaction trace.
  189. type txTraceResult struct {
  190. Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
  191. Error string `json:"error,omitempty"` // Trace failure produced by the tracer
  192. }
  193. // blockTraceTask represents a single block trace task when an entire chain is
  194. // being traced.
  195. type blockTraceTask struct {
  196. statedb *state.StateDB // Intermediate state prepped for tracing
  197. block *types.Block // Block to trace the transactions from
  198. rootref common.Hash // Trie root reference held for this task
  199. results []*txTraceResult // Trace results procudes by the task
  200. // Quorum
  201. privateStateDb *state.StateDB
  202. privateStateRepo mps.PrivateStateRepository
  203. }
  204. // blockTraceResult represets the results of tracing a single block when an entire
  205. // chain is being traced.
  206. type blockTraceResult struct {
  207. Block hexutil.Uint64 `json:"block"` // Block number corresponding to this trace
  208. Hash common.Hash `json:"hash"` // Block hash corresponding to this trace
  209. Traces []*txTraceResult `json:"traces"` // Trace results produced by the task
  210. }
  211. // txTraceTask represents a single transaction trace task when an entire block
  212. // is being traced.
  213. type txTraceTask struct {
  214. statedb *state.StateDB // Intermediate state prepped for tracing
  215. index int // Transaction offset in the block
  216. // Quorum
  217. privateStateDb *state.StateDB
  218. privateStateRepo mps.PrivateStateRepository
  219. }
  220. // TraceChain returns the structured logs created during the execution of EVM
  221. // between two blocks (excluding start) and returns them as a JSON object.
  222. func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { // Fetch the block interval that we want to trace
  223. from, err := api.blockByNumber(ctx, start)
  224. if err != nil {
  225. return nil, err
  226. }
  227. to, err := api.blockByNumber(ctx, end)
  228. if err != nil {
  229. return nil, err
  230. }
  231. if from.Number().Cmp(to.Number()) >= 0 {
  232. return nil, fmt.Errorf("end block (#%d) needs to come after start block (#%d)", end, start)
  233. }
  234. return api.traceChain(ctx, from, to, config)
  235. }
  236. // traceChain configures a new tracer according to the provided configuration, and
  237. // executes all the transactions contained within. The return value will be one item
  238. // per transaction, dependent on the requested tracer.
  239. func (api *API) traceChain(ctx context.Context, start, end *types.Block, config *TraceConfig) (*rpc.Subscription, error) {
  240. // Tracing a chain is a **long** operation, only do with subscriptions
  241. notifier, supported := rpc.NotifierFromContext(ctx)
  242. if !supported {
  243. return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
  244. }
  245. sub := notifier.CreateSubscription()
  246. // Prepare all the states for tracing. Note this procedure can take very
  247. // long time. Timeout mechanism is necessary.
  248. reexec := defaultTraceReexec
  249. if config != nil && config.Reexec != nil {
  250. reexec = *config.Reexec
  251. }
  252. // Quorum
  253. psm, err := api.chainContext(ctx).PrivateStateManager().ResolveForUserContext(ctx)
  254. if err != nil {
  255. return nil, err
  256. }
  257. // End Quorum
  258. blocks := int(end.NumberU64() - start.NumberU64())
  259. threads := runtime.NumCPU()
  260. if threads > blocks {
  261. threads = blocks
  262. }
  263. var (
  264. pend = new(sync.WaitGroup)
  265. tasks = make(chan *blockTraceTask, threads)
  266. results = make(chan *blockTraceTask, threads)
  267. localctx = context.Background()
  268. )
  269. for th := 0; th < threads; th++ {
  270. pend.Add(1)
  271. go func() {
  272. defer pend.Done()
  273. // Fetch and execute the next block trace tasks
  274. for task := range tasks {
  275. signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
  276. blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), nil)
  277. // Trace all the transactions contained within
  278. for i, tx := range task.block.Transactions() {
  279. msg, _ := tx.AsMessage(signer)
  280. msg = api.clearMessageDataIfNonParty(msg, psm) // Quorum
  281. txctx := &txTraceContext{
  282. index: i,
  283. hash: tx.Hash(),
  284. block: task.block.Hash(),
  285. tx: tx,
  286. }
  287. res, err := api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, task.privateStateDb, task.privateStateRepo, config)
  288. if err != nil {
  289. task.results[i] = &txTraceResult{Error: err.Error()}
  290. log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
  291. break
  292. }
  293. // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
  294. eip158 := api.backend.ChainConfig().IsEIP158(task.block.Number())
  295. task.statedb.Finalise(eip158)
  296. task.privateStateDb.Finalise(eip158)
  297. task.results[i] = &txTraceResult{Result: res}
  298. }
  299. // Stream the result back to the user or abort on teardown
  300. select {
  301. case results <- task:
  302. case <-notifier.Closed():
  303. return
  304. }
  305. }
  306. }()
  307. }
  308. // Start a goroutine to feed all the blocks into the tracers
  309. begin := time.Now()
  310. go func() {
  311. var (
  312. logged time.Time
  313. number uint64
  314. traced uint64
  315. failed error
  316. parent common.Hash
  317. statedb *state.StateDB
  318. // Quorum
  319. privateStateRepo mps.PrivateStateRepository
  320. privateState *state.StateDB
  321. )
  322. // Ensure everything is properly cleaned up on any exit path
  323. defer func() {
  324. close(tasks)
  325. pend.Wait()
  326. switch {
  327. case failed != nil:
  328. log.Warn("Chain tracing failed", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin), "err", failed)
  329. case number < end.NumberU64():
  330. log.Warn("Chain tracing aborted", "start", start.NumberU64(), "end", end.NumberU64(), "abort", number, "transactions", traced, "elapsed", time.Since(begin))
  331. default:
  332. log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin))
  333. }
  334. close(results)
  335. }()
  336. // Feed all the blocks both into the tracer, as well as fast process concurrently
  337. for number = start.NumberU64(); number < end.NumberU64(); number++ {
  338. // Stop tracing if interruption was requested
  339. select {
  340. case <-notifier.Closed():
  341. return
  342. default:
  343. }
  344. // Print progress logs if long enough time elapsed
  345. if time.Since(logged) > 8*time.Second {
  346. logged = time.Now()
  347. log.Info("Tracing chain segment", "start", start.NumberU64(), "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin))
  348. }
  349. // Retrieve the parent state to trace on top
  350. block, err := api.blockByNumber(localctx, rpc.BlockNumber(number))
  351. if err != nil {
  352. failed = err
  353. break
  354. }
  355. // Prepare the statedb for tracing. Don't use the live database for
  356. // tracing to avoid persisting state junks into the database.
  357. statedb, privateStateRepo, err = api.backend.StateAtBlock(localctx, block, reexec, statedb, false)
  358. if err != nil {
  359. failed = err
  360. break
  361. }
  362. if statedb.Database().TrieDB() != nil {
  363. // Hold the reference for tracer, will be released at the final stage
  364. statedb.Database().TrieDB().Reference(block.Root(), common.Hash{})
  365. // Release the parent state because it's already held by the tracer
  366. if parent != (common.Hash{}) {
  367. statedb.Database().TrieDB().Dereference(parent)
  368. }
  369. }
  370. parent = block.Root()
  371. privateState, err = privateStateRepo.StatePSI(psm.ID)
  372. if err != nil {
  373. failed = err
  374. break
  375. }
  376. next, err := api.blockByNumber(localctx, rpc.BlockNumber(number+1))
  377. if err != nil {
  378. failed = err
  379. break
  380. }
  381. // Send the block over to the concurrent tracers (if not in the fast-forward phase)
  382. txs := next.Transactions()
  383. select {
  384. case tasks <- &blockTraceTask{
  385. statedb: statedb.Copy(),
  386. block: next,
  387. rootref: block.Root(),
  388. results: make([]*txTraceResult, len(txs)),
  389. // Quorum
  390. privateStateDb: privateState.Copy(),
  391. privateStateRepo: privateStateRepo,
  392. }:
  393. case <-notifier.Closed():
  394. return
  395. }
  396. traced += uint64(len(txs))
  397. }
  398. }()
  399. // Keep reading the trace results and stream the to the user
  400. go func() {
  401. var (
  402. done = make(map[uint64]*blockTraceResult)
  403. next = start.NumberU64() + 1
  404. )
  405. for res := range results {
  406. // Queue up next received result
  407. result := &blockTraceResult{
  408. Block: hexutil.Uint64(res.block.NumberU64()),
  409. Hash: res.block.Hash(),
  410. Traces: res.results,
  411. }
  412. done[uint64(result.Block)] = result
  413. // Dereference any parent tries held in memory by this task
  414. if res.statedb.Database().TrieDB() != nil {
  415. res.statedb.Database().TrieDB().Dereference(res.rootref)
  416. }
  417. if res.privateStateDb != nil && res.privateStateDb != res.statedb && res.privateStateDb.Database().TrieDB() != nil {
  418. res.privateStateDb.Database().TrieDB().Dereference(res.rootref)
  419. }
  420. // Stream completed traces to the user, aborting on the first error
  421. for result, ok := done[next]; ok; result, ok = done[next] {
  422. if len(result.Traces) > 0 || next == end.NumberU64() {
  423. notifier.Notify(sub.ID, result)
  424. }
  425. delete(done, next)
  426. next++
  427. }
  428. }
  429. }()
  430. return sub, nil
  431. }
  432. // TraceBlockByNumber returns the structured logs created during the execution of
  433. // EVM and returns them as a JSON object.
  434. func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
  435. block, err := api.blockByNumber(ctx, number)
  436. if err != nil {
  437. return nil, err
  438. }
  439. return api.traceBlock(ctx, block, config)
  440. }
  441. // TraceBlockByHash returns the structured logs created during the execution of
  442. // EVM and returns them as a JSON object.
  443. func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
  444. block, err := api.blockByHash(ctx, hash)
  445. if err != nil {
  446. return nil, err
  447. }
  448. return api.traceBlock(ctx, block, config)
  449. }
  450. // TraceBlock returns the structured logs created during the execution of EVM
  451. // and returns them as a JSON object.
  452. func (api *API) TraceBlock(ctx context.Context, blob []byte, config *TraceConfig) ([]*txTraceResult, error) {
  453. block := new(types.Block)
  454. if err := rlp.Decode(bytes.NewReader(blob), block); err != nil {
  455. return nil, fmt.Errorf("could not decode block: %v", err)
  456. }
  457. return api.traceBlock(ctx, block, config)
  458. }
  459. // TraceBlockFromFile returns the structured logs created during the execution of
  460. // EVM and returns them as a JSON object.
  461. func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) {
  462. blob, err := ioutil.ReadFile(file)
  463. if err != nil {
  464. return nil, fmt.Errorf("could not read file: %v", err)
  465. }
  466. return api.TraceBlock(ctx, blob, config)
  467. }
  468. // TraceBadBlock returns the structured logs created during the execution of
  469. // EVM against a block pulled from the pool of bad ones and returns them as a JSON
  470. // object.
  471. func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
  472. for _, block := range rawdb.ReadAllBadBlocks(api.backend.ChainDb()) {
  473. if block.Hash() == hash {
  474. return api.traceBlock(ctx, block, config)
  475. }
  476. }
  477. return nil, fmt.Errorf("bad block %#x not found", hash)
  478. }
  479. // StandardTraceBlockToFile dumps the structured logs created during the
  480. // execution of EVM to the local file system and returns a list of files
  481. // to the caller.
  482. func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
  483. block, err := api.blockByHash(ctx, hash)
  484. if err != nil {
  485. return nil, err
  486. }
  487. return api.standardTraceBlockToFile(ctx, block, config)
  488. }
  489. // StandardTraceBadBlockToFile dumps the structured logs created during the
  490. // execution of EVM against a block pulled from the pool of bad ones to the
  491. // local file system and returns a list of files to the caller.
  492. func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
  493. for _, block := range rawdb.ReadAllBadBlocks(api.backend.ChainDb()) {
  494. if block.Hash() == hash {
  495. return api.standardTraceBlockToFile(ctx, block, config)
  496. }
  497. }
  498. return nil, fmt.Errorf("bad block %#x not found", hash)
  499. }
  500. // traceBlock configures a new tracer according to the provided configuration, and
  501. // executes all the transactions contained within. The return value will be one item
  502. // per transaction, dependent on the requestd tracer.
  503. func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
  504. if block.NumberU64() == 0 {
  505. return nil, errors.New("genesis is not traceable")
  506. }
  507. parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
  508. if err != nil {
  509. return nil, err
  510. }
  511. reexec := defaultTraceReexec
  512. if config != nil && config.Reexec != nil {
  513. reexec = *config.Reexec
  514. }
  515. statedb, privateStateRepo, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
  516. if err != nil {
  517. return nil, err
  518. }
  519. // Quorum
  520. psm, err := api.chainContext(ctx).PrivateStateManager().ResolveForUserContext(ctx)
  521. if err != nil {
  522. return nil, err
  523. }
  524. privateStateDb, err := privateStateRepo.StatePSI(psm.ID)
  525. if err != nil {
  526. return nil, err
  527. }
  528. // End Quorum
  529. // Execute all the transaction contained within the block concurrently
  530. var (
  531. signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
  532. txs = block.Transactions()
  533. results = make([]*txTraceResult, len(txs))
  534. pend = new(sync.WaitGroup)
  535. jobs = make(chan *txTraceTask, len(txs))
  536. )
  537. threads := runtime.NumCPU()
  538. if threads > len(txs) {
  539. threads = len(txs)
  540. }
  541. blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
  542. blockHash := block.Hash()
  543. for th := 0; th < threads; th++ {
  544. pend.Add(1)
  545. go func() {
  546. defer pend.Done()
  547. // Fetch and execute the next transaction trace tasks
  548. for task := range jobs {
  549. tx := txs[task.index]
  550. msg, _ := tx.AsMessage(signer)
  551. msg = api.clearMessageDataIfNonParty(msg, psm)
  552. txctx := &txTraceContext{
  553. index: task.index,
  554. hash: tx.Hash(),
  555. block: blockHash,
  556. tx: tx,
  557. }
  558. res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, task.privateStateDb, task.privateStateRepo, config)
  559. if err != nil {
  560. results[task.index] = &txTraceResult{Error: err.Error()}
  561. continue
  562. }
  563. results[task.index] = &txTraceResult{Result: res}
  564. }
  565. }()
  566. }
  567. // Feed the transactions into the tracers and return
  568. var failed error
  569. for i, tx := range txs {
  570. // Send the trace task over for execution
  571. jobs <- &txTraceTask{
  572. statedb: statedb.Copy(),
  573. index: i,
  574. // Quorum
  575. privateStateDb: privateStateDb.Copy(),
  576. privateStateRepo: privateStateRepo,
  577. }
  578. // Generate the next state snapshot fast without tracing
  579. msg, _ := tx.AsMessage(signer)
  580. privateStateDbToUse := core.PrivateStateDBForTxn(api.chainContext(ctx).Config().IsQuorum, tx, statedb, privateStateDb)
  581. statedb.Prepare(tx.Hash(), block.Hash(), i)
  582. privateStateDbToUse.Prepare(tx.Hash(), block.Hash(), i)
  583. vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, privateStateDbToUse, api.backend.ChainConfig(), vm.Config{})
  584. vmenv.SetCurrentTX(tx)
  585. vmenv.InnerApply = func(innerTx *types.Transaction) error {
  586. return applyInnerTransaction(api.backend.GetBlockchain(), statedb, privateStateDbToUse, block.Header(), tx, vm.Config{}, privateStateRepo.IsMPS(), privateStateRepo, vmenv, innerTx, i)
  587. }
  588. if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
  589. failed = err
  590. break
  591. }
  592. // Finalize the state so any modifications are written to the trie
  593. // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
  594. eip158 := vmenv.ChainConfig().IsEIP158(block.Number())
  595. statedb.Finalise(eip158)
  596. privateStateDb.Finalise(eip158)
  597. }
  598. close(jobs)
  599. pend.Wait()
  600. // If execution failed in between, abort
  601. if failed != nil {
  602. return nil, failed
  603. }
  604. return results, nil
  605. }
  606. // standardTraceBlockToFile configures a new tracer which uses standard JSON output,
  607. // and traces either a full block or an individual transaction. The return value will
  608. // be one filename per transaction traced.
  609. func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
  610. // If we're tracing a single transaction, make sure it's present
  611. if config != nil && config.TxHash != (common.Hash{}) {
  612. if !containsTx(block, config.TxHash) {
  613. return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
  614. }
  615. }
  616. if block.NumberU64() == 0 {
  617. return nil, errors.New("genesis is not traceable")
  618. }
  619. parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
  620. if err != nil {
  621. return nil, err
  622. }
  623. reexec := defaultTraceReexec
  624. if config != nil && config.Reexec != nil {
  625. reexec = *config.Reexec
  626. }
  627. statedb, privateStateRepo, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
  628. if err != nil {
  629. return nil, err
  630. }
  631. psm, err := api.chainContext(ctx).PrivateStateManager().ResolveForUserContext(ctx)
  632. if err != nil {
  633. return nil, err
  634. }
  635. privateStateDb, err := privateStateRepo.StatePSI(psm.ID)
  636. if err != nil {
  637. return nil, err
  638. }
  639. // Retrieve the tracing configurations, or use default values
  640. var (
  641. logConfig vm.LogConfig
  642. txHash common.Hash
  643. )
  644. if config != nil {
  645. logConfig = config.LogConfig
  646. txHash = config.TxHash
  647. }
  648. logConfig.Debug = true
  649. // Execute transaction, either tracing all or just the requested one
  650. var (
  651. dumps []string
  652. signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
  653. chainConfig = api.backend.ChainConfig()
  654. vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
  655. canon = true
  656. )
  657. // Check if there are any overrides: the caller may wish to enable a future
  658. // fork when executing this block. Note, such overrides are only applicable to the
  659. // actual specified block, not any preceding blocks that we have to go through
  660. // in order to obtain the state.
  661. // Therefore, it's perfectly valid to specify `"futureForkBlock": 0`, to enable `futureFork`
  662. if config != nil && config.Overrides != nil {
  663. // Copy the config, to not screw up the main config
  664. // Note: the Clique-part is _not_ deep copied
  665. chainConfigCopy := new(params.ChainConfig)
  666. *chainConfigCopy = *chainConfig
  667. chainConfig = chainConfigCopy
  668. if berlin := config.LogConfig.Overrides.BerlinBlock; berlin != nil {
  669. chainConfig.BerlinBlock = berlin
  670. canon = false
  671. }
  672. }
  673. for i, tx := range block.Transactions() {
  674. // Prepare the trasaction for un-traced execution
  675. var (
  676. msg, _ = tx.AsMessage(signer)
  677. txContext = core.NewEVMTxContext(msg)
  678. vmConf vm.Config
  679. dump *os.File
  680. writer *bufio.Writer
  681. err error
  682. )
  683. // If the transaction needs tracing, swap out the configs
  684. if tx.Hash() == txHash || txHash == (common.Hash{}) {
  685. // Generate a unique temporary file to dump it into
  686. prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
  687. if !canon {
  688. prefix = fmt.Sprintf("%valt-", prefix)
  689. }
  690. dump, err = ioutil.TempFile(os.TempDir(), prefix)
  691. if err != nil {
  692. return nil, err
  693. }
  694. dumps = append(dumps, dump.Name())
  695. // Swap out the noop logger to the standard tracer
  696. writer = bufio.NewWriter(dump)
  697. vmConf = vm.Config{
  698. Debug: true,
  699. Tracer: vm.NewJSONLogger(&logConfig, writer),
  700. EnablePreimageRecording: true,
  701. }
  702. }
  703. // Execute the transaction and flush any traces to disk
  704. // Quorum
  705. privateStateDbToUse := core.PrivateStateDBForTxn(chainConfig.IsQuorum, tx, statedb, privateStateDb)
  706. vmConf.ApplyOnPartyOverride = &psm.ID
  707. vmenv := vm.NewEVM(vmctx, txContext, statedb, privateStateDbToUse, chainConfig, vmConf)
  708. // Quorum
  709. vmenv.SetCurrentTX(tx)
  710. vmenv.InnerApply = func(innerTx *types.Transaction) error {
  711. return applyInnerTransaction(api.backend.GetBlockchain(), statedb, privateStateDbToUse, block.Header(), tx, vmConf, privateStateRepo.IsMPS(), privateStateRepo, vmenv, innerTx, i)
  712. }
  713. msg = api.clearMessageDataIfNonParty(msg, psm)
  714. statedb.Prepare(tx.Hash(), block.Hash(), i)
  715. privateStateDbToUse.Prepare(tx.Hash(), block.Hash(), i)
  716. _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
  717. if writer != nil {
  718. writer.Flush()
  719. }
  720. if dump != nil {
  721. dump.Close()
  722. log.Info("Wrote standard trace", "file", dump.Name())
  723. }
  724. if err != nil {
  725. return dumps, err
  726. }
  727. // Finalize the state so any modifications are written to the trie
  728. // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
  729. eip158 := vmenv.ChainConfig().IsEIP158(block.Number())
  730. statedb.Finalise(eip158)
  731. privateStateDbToUse.Finalise(eip158)
  732. // If we've traced the transaction we were looking for, abort
  733. if tx.Hash() == txHash {
  734. break
  735. }
  736. }
  737. return dumps, nil
  738. }
  739. // containsTx reports whether the transaction with a certain hash
  740. // is contained within the specified block.
  741. func containsTx(block *types.Block, hash common.Hash) bool {
  742. for _, tx := range block.Transactions() {
  743. if tx.Hash() == hash {
  744. return true
  745. }
  746. }
  747. return false
  748. }
  749. // TraceTransaction returns the structured logs created during the execution of EVM
  750. // and returns them as a JSON object.
  751. func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
  752. tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
  753. if err != nil {
  754. return nil, err
  755. }
  756. if tx == nil {
  757. return nil, fmt.Errorf("transaction %#x not found", hash)
  758. }
  759. // It shouldn't happen in practice.
  760. if blockNumber == 0 {
  761. return nil, errors.New("genesis is not traceable")
  762. }
  763. reexec := defaultTraceReexec
  764. if config != nil && config.Reexec != nil {
  765. reexec = *config.Reexec
  766. }
  767. block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
  768. if err != nil {
  769. return nil, err
  770. }
  771. msg, vmctx, statedb, privateState, privateStateRepo, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
  772. if err != nil {
  773. return nil, err
  774. }
  775. txctx := &txTraceContext{
  776. index: int(index),
  777. hash: hash,
  778. block: blockHash,
  779. tx: tx,
  780. }
  781. return api.traceTx(ctx, msg, txctx, vmctx, statedb, privateState, privateStateRepo, config)
  782. }
  783. // TraceCall lets you trace a given eth_call. It collects the structured logs
  784. // created during the execution of EVM if the given transaction was added on
  785. // top of the provided block and returns them as a JSON object.
  786. // You can provide -2 as a block number to trace on top of the pending block.
  787. func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
  788. // Try to retrieve the specified block
  789. var (
  790. err error
  791. block *types.Block
  792. )
  793. if hash, ok := blockNrOrHash.Hash(); ok {
  794. block, err = api.blockByHash(ctx, hash)
  795. } else if number, ok := blockNrOrHash.Number(); ok {
  796. block, err = api.blockByNumber(ctx, number)
  797. } else {
  798. return nil, errors.New("invalid arguments; neither block nor hash specified")
  799. }
  800. if err != nil {
  801. return nil, err
  802. }
  803. // try to recompute the state
  804. reexec := defaultTraceReexec
  805. if config != nil && config.Reexec != nil {
  806. reexec = *config.Reexec
  807. }
  808. statedb, privateStateRepo, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true)
  809. if err != nil {
  810. return nil, err
  811. }
  812. privateStateDb, err := privateStateRepo.DefaultState()
  813. if err != nil {
  814. return nil, err
  815. }
  816. // Apply the customized state rules if required.
  817. if config != nil {
  818. if err := config.StateOverrides.Apply(statedb); err != nil {
  819. return nil, err
  820. }
  821. }
  822. // Execute the trace
  823. msg := args.ToMessage(api.backend.RPCGasCap())
  824. vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
  825. // Quorum: we run the call with privateState as publicState to check if we have a result, if it is not empty, then it is a private call
  826. var noTracerConfig *TraceConfig
  827. var traceConfig *TraceConfig
  828. if config != nil {
  829. // create a new config without the tracer so that we have a ExecutionResult returned by api.traceTx
  830. traceConfig = &TraceConfig{
  831. LogConfig: config.LogConfig,
  832. Tracer: config.Tracer,
  833. Timeout: config.Timeout,
  834. Reexec: config.Reexec,
  835. }
  836. // create a new config with the tracer so that we have a ExecutionResult returned by api.traceTx
  837. noTracerConfig = &TraceConfig{
  838. LogConfig: config.LogConfig,
  839. Timeout: config.Timeout,
  840. Reexec: config.Reexec,
  841. }
  842. }
  843. res, err := api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, privateStateDb, privateStateRepo, noTracerConfig) // test private with no config
  844. if exeRes, ok := res.(*ethapi.ExecutionResult); ok && err == nil && len(exeRes.StructLogs) > 0 { // check there is a result
  845. if config != nil && config.Tracer != nil { // re-run the private call with the custom JS tracer
  846. return api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, privateStateDb, privateStateRepo, traceConfig) // re-run with trace
  847. }
  848. return res, err // return private result with no tracer
  849. } else if err == nil && !ok {
  850. return nil, fmt.Errorf("can not cast traceTx result to *ethapi.ExecutionResult: %#v, %#v", res, err) // better error formatting than "method handler failed"
  851. }
  852. // End Quorum
  853. return api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, privateStateDb, privateStateRepo, traceConfig)
  854. }
  855. // traceTx configures a new tracer according to the provided configuration, and
  856. // executes the given message in the provided environment. The return value will
  857. // be tracer dependent.
  858. func (api *API) traceTx(ctx context.Context, message core.Message, txctx *txTraceContext, vmctx vm.BlockContext, statedb, privateStateDb *state.StateDB, privateStateRepo mps.PrivateStateRepository, config *TraceConfig) (interface{}, error) {
  859. // Assemble the structured logger or the JavaScript tracer
  860. var (
  861. tracer vm.Tracer
  862. err error
  863. txContext = core.NewEVMTxContext(message)
  864. )
  865. switch {
  866. case config != nil && config.Tracer != nil:
  867. // Define a meaningful timeout of a single transaction trace
  868. timeout := defaultTraceTimeout
  869. if config.Timeout != nil {
  870. if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
  871. return nil, err
  872. }
  873. }
  874. // Constuct the JavaScript tracer to execute with
  875. if tracer, err = New(*config.Tracer, txContext); err != nil {
  876. return nil, err
  877. }
  878. // Handle timeouts and RPC cancellations
  879. deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
  880. go func() {
  881. <-deadlineCtx.Done()
  882. if deadlineCtx.Err() == context.DeadlineExceeded {
  883. tracer.(*Tracer).Stop(errors.New("execution timeout"))
  884. }
  885. }()
  886. defer cancel()
  887. case config == nil:
  888. tracer = vm.NewStructLogger(nil)
  889. default:
  890. tracer = vm.NewStructLogger(config.LogConfig)
  891. }
  892. // Quorum
  893. // Set the private state to public state if it is not a private tx
  894. privateStateDbToUse := core.PrivateStateDBForTxn(api.backend.ChainConfig().IsQuorum, txctx.tx, statedb, privateStateDb)
  895. psm, err := api.chainContext(ctx).PrivateStateManager().ResolveForUserContext(ctx)
  896. if err != nil {
  897. return nil, fmt.Errorf("tracing failed: %w", err)
  898. }
  899. // Run the transaction with tracing enabled.
  900. vmconf := &vm.Config{Debug: true, Tracer: tracer, ApplyOnPartyOverride: &psm.ID}
  901. vmenv := vm.NewEVM(vmctx, txContext, statedb, privateStateDbToUse, api.backend.ChainConfig(), *vmconf)
  902. vmenv.SetCurrentTX(txctx.tx)
  903. vmenv.InnerApply = func(innerTx *types.Transaction) error {
  904. header, err := api.backend.HeaderByHash(ctx, txctx.block)
  905. if err != nil {
  906. return err
  907. }
  908. return applyInnerTransaction(api.backend.GetBlockchain(), statedb, privateStateDbToUse, header, txctx.tx, *vmconf, privateStateRepo.IsMPS(), privateStateRepo, vmenv, innerTx, txctx.index)
  909. }
  910. // End Quorum
  911. // Call Prepare to clear out the statedb access list
  912. statedb.Prepare(txctx.hash, txctx.block, txctx.index)
  913. privateStateDbToUse.Prepare(txctx.hash, txctx.block, txctx.index)
  914. result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
  915. if err != nil {
  916. return nil, fmt.Errorf("tracing failed: %w", err)
  917. }
  918. // Depending on the tracer type, format and return the output.
  919. switch tracer := tracer.(type) {
  920. case *vm.StructLogger:
  921. // If the result contains a revert reason, return it.
  922. returnVal := fmt.Sprintf("%x", result.Return())
  923. if len(result.Revert()) > 0 {
  924. returnVal = fmt.Sprintf("%x", result.Revert())
  925. }
  926. return &ethapi.ExecutionResult{
  927. Gas: result.UsedGas,
  928. Failed: result.Failed(),
  929. ReturnValue: returnVal,
  930. StructLogs: ethapi.FormatLogs(tracer.StructLogs()),
  931. }, nil
  932. case *Tracer:
  933. return tracer.GetResult()
  934. default:
  935. panic(fmt.Sprintf("bad tracer type %T", tracer))
  936. }
  937. }
  938. // APIs return the collection of RPC services the tracer package offers.
  939. func APIs(backend Backend) []rpc.API {
  940. // Append all the local APIs and return
  941. return []rpc.API{
  942. {
  943. Namespace: "debug",
  944. Version: "1.0",
  945. Service: NewAPI(backend),
  946. Public: false,
  947. },
  948. }
  949. }
  950. // Quorum
  951. // clearMessageDataIfNonParty sets the message data to empty hash in case the private state is not party to the
  952. // transaction. The effect is that when the private tx payload is resolved using the privacy manager the private part of
  953. // the transaction is not retrieved and the transaction is being executed as if the node/private state is not party to
  954. // the transaction.
  955. func (api *API) clearMessageDataIfNonParty(msg types.Message, psm *mps.PrivateStateMetadata) types.Message {
  956. if msg.IsPrivate() {
  957. _, managedParties, _, _, _ := private.P.Receive(common.BytesToEncryptedPayloadHash(msg.Data()))
  958. if api.chainContext(nil).PrivateStateManager().NotIncludeAny(psm, managedParties...) {
  959. return msg.WithEmptyPrivateData(true)
  960. }
  961. }
  962. return msg
  963. }
  964. func applyInnerTransaction(bc *core.BlockChain, stateDB *state.StateDB, privateStateDB *state.StateDB, header *types.Header, outerTx *types.Transaction, evmConf vm.Config, forceNonParty bool, privateStateRepo mps.PrivateStateRepository, vmenv *vm.EVM, innerTx *types.Transaction, txIndex int) error {
  965. var (
  966. author *common.Address = nil // ApplyTransaction will determine the author from the header so we won't do it here
  967. gp *core.GasPool = new(core.GasPool).AddGas(outerTx.Gas())
  968. usedGas uint64 = 0
  969. )
  970. return core.ApplyInnerTransaction(bc, author, gp, stateDB, privateStateDB, header, outerTx, &usedGas, evmConf, forceNonParty, privateStateRepo, vmenv, innerTx, txIndex)
  971. }