public_block_chain_api.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. package ethapi
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "github.com/ethereum/go-ethereum/common"
  7. "github.com/ethereum/go-ethereum/common/hexutil"
  8. "github.com/ethereum/go-ethereum/consensus"
  9. "github.com/ethereum/go-ethereum/core"
  10. "github.com/ethereum/go-ethereum/core/state"
  11. "github.com/ethereum/go-ethereum/core/types"
  12. "github.com/ethereum/go-ethereum/core/vm"
  13. "github.com/ethereum/go-ethereum/crypto"
  14. "github.com/ethereum/go-ethereum/log"
  15. "github.com/ethereum/go-ethereum/rpc"
  16. "math/big"
  17. "time"
  18. )
  19. // PublicBlockChainAPI provides an API to access the Ethereum blockchain.
  20. // It offers only methods that operate on public data that is freely available to anyone.
  21. type PublicBlockChainAPI struct {
  22. b Backend
  23. }
  24. // NewPublicBlockChainAPI creates a new Ethereum blockchain API.
  25. func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI {
  26. return &PublicBlockChainAPI{b}
  27. }
  28. // Call executes the given transaction on the state for the given block number.
  29. //
  30. // Additionally, the caller can specify a batch of contract for fields overriding.
  31. //
  32. // Note, this function doesn't make and changes in the state/blockchain and is
  33. // useful to execute and retrieve values.
  34. func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
  35. result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, vm.Config{}, 5*time.Second, s.b.RPCGasCap())
  36. if err != nil {
  37. return nil, err
  38. }
  39. // If the result contains a revert reason, try to unpack and return it.
  40. if len(result.Revert()) > 0 {
  41. return nil, newRevertError(result)
  42. }
  43. return result.Return(), result.Err
  44. }
  45. func (s *PublicBlockChainAPI) NewCall(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (CallResult, error) {
  46. result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, vm.Config{}, 5*time.Second, s.b.RPCGasCap())
  47. if err != nil {
  48. return CallResult{Success: false, Msg: err.Error()}, nil
  49. } else {
  50. if len(result.Revert()) > 0 {
  51. revertErr := newRevertError(result)
  52. return CallResult{Success: false, Return: result.Return(), Msg: revertErr.Error()}, nil
  53. }
  54. return CallResult{Success: true, Return: result.Return()}, nil
  55. }
  56. }
  57. // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config.
  58. func (api *PublicBlockChainAPI) ChainId() (*hexutil.Big, error) {
  59. // if current block is at or past the EIP-155 replay-protection fork block, return chainID from config
  60. if config := api.b.ChainConfig(); config.IsEIP155(api.b.CurrentBlock().Number()) {
  61. return (*hexutil.Big)(config.ChainID), nil
  62. }
  63. return nil, fmt.Errorf("chain not synced beyond EIP-155 replay-protection fork block")
  64. }
  65. // BlockNumber returns the block number of the chain head.
  66. func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 {
  67. header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
  68. return hexutil.Uint64(header.Number.Uint64())
  69. }
  70. // GetBalance returns the amount of wei for the given address in the state of the
  71. // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
  72. // block numbers are also allowed.
  73. func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
  74. state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
  75. if state == nil || err != nil {
  76. return nil, err
  77. }
  78. return (*hexutil.Big)(state.GetBalance(address)), state.Error()
  79. }
  80. // BatchCall executes a series of transactions on the state of a given block as base.
  81. // The base state can be overridden once before transactions are executed.
  82. //
  83. // Additionally, each call can override block context fields such as number.
  84. //
  85. // Note, this function doesn't make any changes in the state/blockchain and is
  86. // useful to execute and retrieve values.
  87. func (s *PublicBlockChainAPI) BatchCall(ctx context.Context, config BatchCallConfig) ([]CallResult, error) {
  88. state, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, config.Block)
  89. if state == nil || err != nil {
  90. return nil, err
  91. }
  92. // State overrides are applied once before all calls
  93. if err := config.StateOverrides.Apply(state); err != nil {
  94. return nil, err
  95. }
  96. // Setup context so it may be cancelled before the calls completed
  97. // or, in case of unmetered gas, setup a context with a timeout.
  98. var (
  99. cancel context.CancelFunc
  100. //timeout = s.b.RPCEVMTimeout()
  101. timeout = time.Duration(5000000000)
  102. )
  103. if timeout > 0 {
  104. ctx, cancel = context.WithTimeout(ctx, timeout)
  105. } else {
  106. ctx, cancel = context.WithCancel(ctx)
  107. }
  108. // Make sure the context is cancelled when the call has completed
  109. // this makes sure resources are cleaned up.
  110. defer cancel()
  111. var (
  112. results []CallResult
  113. // Each tx and all the series of txes shouldn't consume more gas than cap
  114. globalGasCap = s.b.RPCGasCap()
  115. gp = new(core.GasPool).AddGas(globalGasCap)
  116. )
  117. for _, call := range config.Calls {
  118. blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
  119. if call.BlockOverrides != nil {
  120. call.BlockOverrides.Apply(&blockContext)
  121. }
  122. result, doCallErr := doCall(ctx, s.b, call.CallArgs, state, header, timeout, gp, &blockContext)
  123. if doCallErr != nil {
  124. results = append(results, CallResult{Success: false, Msg: doCallErr.Error()})
  125. } else {
  126. if len(result.Revert()) > 0 {
  127. revertErr := newRevertError(result)
  128. results = append(results, CallResult{Success: false, Return: result.Return(), Msg: revertErr.Error()})
  129. } else {
  130. results = append(results, CallResult{Success: true, Return: result.Return()})
  131. }
  132. }
  133. }
  134. return results, nil
  135. }
  136. // EstimateGas returns an estimate of the amount of gas needed to execute the
  137. // given transaction against the current pending block.
  138. func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
  139. bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
  140. if blockNrOrHash != nil {
  141. bNrOrHash = *blockNrOrHash
  142. }
  143. return DoEstimateGas(ctx, s.b, args, bNrOrHash, s.b.RPCGasCap())
  144. }
  145. // GetProof returns the Merkle-proof for a given account and optionally some storage keys.
  146. func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
  147. state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
  148. if state == nil || err != nil {
  149. return nil, err
  150. }
  151. storageTrie := state.StorageTrie(address)
  152. storageHash := types.EmptyRootHash
  153. codeHash := state.GetCodeHash(address)
  154. storageProof := make([]StorageResult, len(storageKeys))
  155. // if we have a storageTrie, (which means the account exists), we can update the storagehash
  156. if storageTrie != nil {
  157. storageHash = storageTrie.Hash()
  158. } else {
  159. // no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
  160. codeHash = crypto.Keccak256Hash(nil)
  161. }
  162. // create the proof for the storageKeys
  163. for i, key := range storageKeys {
  164. if storageTrie != nil {
  165. proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
  166. if storageError != nil {
  167. return nil, storageError
  168. }
  169. storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
  170. } else {
  171. storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
  172. }
  173. }
  174. // create the accountProof
  175. accountProof, proofErr := state.GetProof(address)
  176. if proofErr != nil {
  177. return nil, proofErr
  178. }
  179. return &AccountResult{
  180. Address: address,
  181. AccountProof: toHexSlice(accountProof),
  182. Balance: (*hexutil.Big)(state.GetBalance(address)),
  183. CodeHash: codeHash,
  184. Nonce: hexutil.Uint64(state.GetNonce(address)),
  185. StorageHash: storageHash,
  186. StorageProof: storageProof,
  187. }, state.Error()
  188. }
  189. // GetHeaderByNumber returns the requested canonical block header.
  190. // * When blockNr is -1 the chain head is returned.
  191. // * When blockNr is -2 the pending chain head is returned.
  192. func (s *PublicBlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
  193. header, err := s.b.HeaderByNumber(ctx, number)
  194. if header != nil && err == nil {
  195. response := s.rpcMarshalHeader(ctx, header)
  196. if number == rpc.PendingBlockNumber {
  197. // Pending header need to nil out a few fields
  198. for _, field := range []string{"hash", "nonce", "miner"} {
  199. response[field] = nil
  200. }
  201. }
  202. return response, err
  203. }
  204. return nil, err
  205. }
  206. // GetHeaderByHash returns the requested header by hash.
  207. func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
  208. header, _ := s.b.HeaderByHash(ctx, hash)
  209. if header != nil {
  210. return s.rpcMarshalHeader(ctx, header)
  211. }
  212. return nil
  213. }
  214. // GetBlockByNumber returns the requested canonical block.
  215. // - When blockNr is -1 the chain head is returned.
  216. // - When blockNr is -2 the pending chain head is returned.
  217. // - When fullTx is true all transactions in the block are returned, otherwise
  218. // only the transaction hash is returned.
  219. func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
  220. block, err := s.b.BlockByNumber(ctx, number)
  221. if block != nil && err == nil {
  222. response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
  223. if err == nil && number == rpc.PendingBlockNumber {
  224. // Pending blocks need to nil out a few fields
  225. for _, field := range []string{"hash", "nonce", "miner"} {
  226. response[field] = nil
  227. }
  228. }
  229. return response, err
  230. }
  231. return nil, err
  232. }
  233. // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
  234. // detail, otherwise only the transaction hash is returned.
  235. func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
  236. block, err := s.b.BlockByHash(ctx, hash)
  237. if block != nil {
  238. return s.rpcMarshalBlock(ctx, block, true, fullTx)
  239. }
  240. return nil, err
  241. }
  242. func (s *PublicBlockChainAPI) Health() bool {
  243. if rpc.RpcServingTimer != nil {
  244. return rpc.RpcServingTimer.Percentile(0.75) < float64(UnHealthyTimeout)
  245. }
  246. return true
  247. }
  248. // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
  249. // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
  250. func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
  251. block, err := s.b.BlockByNumber(ctx, blockNr)
  252. if block != nil {
  253. uncles := block.Uncles()
  254. if index >= hexutil.Uint(len(uncles)) {
  255. log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index)
  256. return nil, nil
  257. }
  258. block = types.NewBlockWithHeader(uncles[index])
  259. return s.rpcMarshalBlock(ctx, block, false, false)
  260. }
  261. return nil, err
  262. }
  263. // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
  264. // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
  265. func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
  266. block, err := s.b.BlockByHash(ctx, blockHash)
  267. if block != nil {
  268. uncles := block.Uncles()
  269. if index >= hexutil.Uint(len(uncles)) {
  270. log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index)
  271. return nil, nil
  272. }
  273. block = types.NewBlockWithHeader(uncles[index])
  274. return s.rpcMarshalBlock(ctx, block, false, false)
  275. }
  276. return nil, err
  277. }
  278. // GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
  279. func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
  280. if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
  281. n := hexutil.Uint(len(block.Uncles()))
  282. return &n
  283. }
  284. return nil
  285. }
  286. // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
  287. func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
  288. if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
  289. n := hexutil.Uint(len(block.Uncles()))
  290. return &n
  291. }
  292. return nil
  293. }
  294. // GetCode returns the code stored at the given address in the state for the given block number.
  295. func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
  296. state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
  297. if state == nil || err != nil {
  298. return nil, err
  299. }
  300. code := state.GetCode(address)
  301. return code, state.Error()
  302. }
  303. // GetStorageAt returns the storage from the state at the given address, key and
  304. // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
  305. // numbers are also allowed.
  306. func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
  307. state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
  308. if state == nil || err != nil {
  309. return nil, err
  310. }
  311. res := state.GetState(address, common.HexToHash(key))
  312. return res[:], state.Error()
  313. }
  314. // GetDiffAccounts returns changed accounts in a specific block number.
  315. func (s *PublicBlockChainAPI) GetDiffAccounts(ctx context.Context, blockNr rpc.BlockNumber) ([]common.Address, error) {
  316. if s.b.Chain() == nil {
  317. return nil, fmt.Errorf("blockchain not support get diff accounts")
  318. }
  319. header, err := s.b.HeaderByNumber(ctx, blockNr)
  320. if err != nil {
  321. return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
  322. }
  323. accounts, err := s.b.Chain().GetDiffAccounts(header.Hash())
  324. if err == nil || !errors.Is(err, core.ErrDiffLayerNotFound) {
  325. return accounts, err
  326. }
  327. // Replay the block when diff layer not found, it is very slow.
  328. block, err := s.b.BlockByNumber(ctx, blockNr)
  329. if err != nil {
  330. return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
  331. }
  332. _, statedb, err := s.replay(ctx, block, nil)
  333. if err != nil {
  334. return nil, err
  335. }
  336. return statedb.GetDirtyAccounts(), nil
  337. }
  338. func (s *PublicBlockChainAPI) needToReplay(ctx context.Context, block *types.Block, accounts []common.Address) (bool, error) {
  339. receipts, err := s.b.GetReceipts(ctx, block.Hash())
  340. if err != nil || len(receipts) != len(block.Transactions()) {
  341. return false, fmt.Errorf("receipt incorrect for block number (%d): %v", block.NumberU64(), err)
  342. }
  343. accountSet := make(map[common.Address]struct{}, len(accounts))
  344. for _, account := range accounts {
  345. accountSet[account] = struct{}{}
  346. }
  347. spendValueMap := make(map[common.Address]int64, len(accounts))
  348. receiveValueMap := make(map[common.Address]int64, len(accounts))
  349. signer := types.MakeSigner(s.b.ChainConfig(), block.Number())
  350. for index, tx := range block.Transactions() {
  351. receipt := receipts[index]
  352. from, err := types.Sender(signer, tx)
  353. if err != nil {
  354. return false, fmt.Errorf("get sender for tx failed: %v", err)
  355. }
  356. if _, exists := accountSet[from]; exists {
  357. spendValueMap[from] += int64(receipt.GasUsed) * tx.GasPrice().Int64()
  358. if receipt.Status == types.ReceiptStatusSuccessful {
  359. spendValueMap[from] += tx.Value().Int64()
  360. }
  361. }
  362. if tx.To() == nil {
  363. continue
  364. }
  365. if _, exists := accountSet[*tx.To()]; exists && receipt.Status == types.ReceiptStatusSuccessful {
  366. receiveValueMap[*tx.To()] += tx.Value().Int64()
  367. }
  368. }
  369. parent, err := s.b.BlockByHash(ctx, block.ParentHash())
  370. if err != nil {
  371. return false, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
  372. }
  373. parentState, err := s.b.Chain().StateAt(parent.Root())
  374. if err != nil {
  375. return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64()-1, err)
  376. }
  377. currentState, err := s.b.Chain().StateAt(block.Root())
  378. if err != nil {
  379. return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64(), err)
  380. }
  381. for _, account := range accounts {
  382. parentBalance := parentState.GetBalance(account).Int64()
  383. currentBalance := currentState.GetBalance(account).Int64()
  384. if receiveValueMap[account]-spendValueMap[account] != currentBalance-parentBalance {
  385. return true, nil
  386. }
  387. }
  388. return false, nil
  389. }
  390. func (s *PublicBlockChainAPI) replay(ctx context.Context, block *types.Block, accounts []common.Address) (*types.DiffAccountsInBlock, *state.StateDB, error) {
  391. result := &types.DiffAccountsInBlock{
  392. Number: block.NumberU64(),
  393. BlockHash: block.Hash(),
  394. Transactions: make([]types.DiffAccountsInTx, 0),
  395. }
  396. parent, err := s.b.BlockByHash(ctx, block.ParentHash())
  397. if err != nil {
  398. return nil, nil, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
  399. }
  400. statedb, err := s.b.Chain().StateAt(parent.Root())
  401. if err != nil {
  402. return nil, nil, fmt.Errorf("state not found for block number (%d): %v", block.NumberU64()-1, err)
  403. }
  404. accountSet := make(map[common.Address]struct{}, len(accounts))
  405. for _, account := range accounts {
  406. accountSet[account] = struct{}{}
  407. }
  408. // Recompute transactions.
  409. signer := types.MakeSigner(s.b.ChainConfig(), block.Number())
  410. for _, tx := range block.Transactions() {
  411. // Skip data empty tx and to is one of the interested accounts tx.
  412. skip := false
  413. if len(tx.Data()) == 0 {
  414. skip = true
  415. } else if to := tx.To(); to != nil {
  416. if _, exists := accountSet[*to]; exists {
  417. skip = true
  418. }
  419. }
  420. diffTx := types.DiffAccountsInTx{
  421. TxHash: tx.Hash(),
  422. Accounts: make(map[common.Address]*big.Int, len(accounts)),
  423. }
  424. if !skip {
  425. // Record account balance
  426. for _, account := range accounts {
  427. diffTx.Accounts[account] = statedb.GetBalance(account)
  428. }
  429. }
  430. // Apply transaction
  431. msg, _ := tx.AsMessage(signer)
  432. txContext := core.NewEVMTxContext(msg)
  433. context := core.NewEVMBlockContext(block.Header(), s.b.Chain(), nil)
  434. vmenv := vm.NewEVM(context, txContext, statedb, s.b.ChainConfig(), vm.Config{})
  435. if posa, ok := s.b.Engine().(consensus.PoSA); ok {
  436. if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
  437. balance := statedb.GetBalance(consensus.SystemAddress)
  438. if balance.Cmp(common.Big0) > 0 {
  439. statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
  440. statedb.AddBalance(block.Header().Coinbase, balance)
  441. }
  442. }
  443. }
  444. if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
  445. return nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
  446. }
  447. statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
  448. if !skip {
  449. // Compute account balance diff.
  450. for _, account := range accounts {
  451. diffTx.Accounts[account] = new(big.Int).Sub(statedb.GetBalance(account), diffTx.Accounts[account])
  452. if diffTx.Accounts[account].Cmp(big.NewInt(0)) == 0 {
  453. delete(diffTx.Accounts, account)
  454. }
  455. }
  456. if len(diffTx.Accounts) != 0 {
  457. result.Transactions = append(result.Transactions, diffTx)
  458. }
  459. }
  460. }
  461. return result, statedb, nil
  462. }
  463. // GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
  464. func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, blockNr rpc.BlockNumber, accounts []common.Address) (*types.DiffAccountsInBlock, error) {
  465. if s.b.Chain() == nil {
  466. return nil, fmt.Errorf("blockchain not support get diff accounts")
  467. }
  468. block, err := s.b.BlockByNumber(ctx, blockNr)
  469. if err != nil {
  470. return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
  471. }
  472. needReplay, err := s.needToReplay(ctx, block, accounts)
  473. if err != nil {
  474. return nil, err
  475. }
  476. if !needReplay {
  477. return &types.DiffAccountsInBlock{
  478. Number: uint64(blockNr),
  479. BlockHash: block.Hash(),
  480. Transactions: make([]types.DiffAccountsInTx, 0),
  481. }, nil
  482. }
  483. result, _, err := s.replay(ctx, block, accounts)
  484. return result, err
  485. }
  486. // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
  487. // a `PublicBlockchainAPI`.
  488. func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
  489. fields := RPCMarshalHeader(header)
  490. fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
  491. return fields
  492. }
  493. // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
  494. // a `PublicBlockchainAPI`.
  495. func (s *PublicBlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
  496. fields, err := RPCMarshalBlock(b, inclTx, fullTx)
  497. if err != nil {
  498. return nil, err
  499. }
  500. if inclTx {
  501. fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, b.Hash()))
  502. }
  503. return fields, err
  504. }
  505. // CreateAccessList creates a EIP-2930 type AccessList for the given transaction.
  506. // Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
  507. func (s *PublicBlockChainAPI) CreateAccessList(ctx context.Context, args SendTxArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
  508. bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
  509. if blockNrOrHash != nil {
  510. bNrOrHash = *blockNrOrHash
  511. }
  512. acl, gasUsed, vmerr, err := AccessList(ctx, s.b, bNrOrHash, args)
  513. if err != nil {
  514. return nil, err
  515. }
  516. result := &accessListResult{Accesslist: &acl, GasUsed: hexutil.Uint64(gasUsed)}
  517. if vmerr != nil {
  518. result.Error = vmerr.Error()
  519. }
  520. return result, nil
  521. }