state_processor.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // Copyright 2015 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 core
  17. import (
  18. "errors"
  19. "fmt"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/consensus"
  22. "github.com/ethereum/go-ethereum/consensus/misc"
  23. "github.com/ethereum/go-ethereum/core/mps"
  24. "github.com/ethereum/go-ethereum/core/state"
  25. "github.com/ethereum/go-ethereum/core/types"
  26. "github.com/ethereum/go-ethereum/core/vm"
  27. "github.com/ethereum/go-ethereum/crypto"
  28. "github.com/ethereum/go-ethereum/log"
  29. "github.com/ethereum/go-ethereum/params"
  30. "github.com/ethereum/go-ethereum/permission/core"
  31. "github.com/ethereum/go-ethereum/private"
  32. )
  33. // StateProcessor is a basic Processor, which takes care of transitioning
  34. // state from one point to another.
  35. //
  36. // StateProcessor implements Processor.
  37. type StateProcessor struct {
  38. config *params.ChainConfig // Chain configuration options
  39. bc *BlockChain // Canonical block chain
  40. engine consensus.Engine // Consensus engine used for block rewards
  41. }
  42. // NewStateProcessor initialises a new StateProcessor.
  43. func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor {
  44. return &StateProcessor{
  45. config: config,
  46. bc: bc,
  47. engine: engine,
  48. }
  49. }
  50. // Process processes the state changes according to the Ethereum rules by running
  51. // the transaction messages using the statedb and applying any rewards to both
  52. // the processor (coinbase) and any included uncles.
  53. //
  54. // Process returns the receipts and logs accumulated during the process and
  55. // returns the amount of gas that was used in the process. If any of the
  56. // transactions failed to execute due to insufficient gas it will return an error.
  57. //
  58. // Quorum: Private transactions are handled for the following:
  59. //
  60. // 1. On original single private state (SPS) design
  61. // 2. On multiple private states (MPS) design
  62. // 3. Contract extension callback (p.bc.CheckAndSetPrivateState)
  63. func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, privateStateRepo mps.PrivateStateRepository, cfg vm.Config) (types.Receipts, types.Receipts, []*types.Log, uint64, error) {
  64. var (
  65. receipts types.Receipts
  66. usedGas = new(uint64)
  67. header = block.Header()
  68. allLogs []*types.Log
  69. gp = new(GasPool).AddGas(block.GasLimit())
  70. privateReceipts types.Receipts
  71. )
  72. // Mutate the block and state according to any hard-fork specs
  73. if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
  74. misc.ApplyDAOHardFork(statedb)
  75. }
  76. blockContext := NewEVMBlockContext(header, p.bc, nil)
  77. // Iterate over and process the individual transactions
  78. for i, tx := range block.Transactions() {
  79. mpsReceipt, err := handleMPS(i, tx, gp, usedGas, cfg, statedb, privateStateRepo, p.config, p.bc, header, false, false)
  80. if err != nil {
  81. return nil, nil, nil, 0, err
  82. }
  83. // handling transaction in 2 scenarios:
  84. // 1. For MPS, the target private state being applied would be the EmptyPrivateState.
  85. // This must be last to avoid contract address collisions.
  86. // 2. For orignal SPS design, the target private state is the single private state
  87. //
  88. // in both cases, privateStateRepo is responsible to return the appropriate
  89. // private state for execution and a bool flag to enable the privacy execution
  90. privateStateDB, err := privateStateRepo.DefaultState()
  91. if err != nil {
  92. return nil, nil, nil, 0, err
  93. }
  94. privateStateDB.Prepare(tx.Hash(), block.Hash(), i)
  95. statedb.Prepare(tx.Hash(), block.Hash(), i)
  96. privateStateDBToUse := PrivateStateDBForTxn(p.config.IsQuorum, tx, statedb, privateStateDB)
  97. // Quorum - check for account permissions to execute the transaction
  98. if core.IsV2Permission() {
  99. if err := core.CheckAccountPermission(tx.From(), tx.To(), tx.Value(), tx.Data(), tx.Gas(), tx.GasPrice()); err != nil {
  100. return nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
  101. }
  102. }
  103. if p.config.IsQuorum && !p.config.IsGasPriceEnabled(header.Number) && tx.GasPrice() != nil && tx.GasPrice().Cmp(common.Big0) > 0 {
  104. return nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), ErrInvalidGasPrice)
  105. }
  106. msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number))
  107. if err != nil {
  108. return nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
  109. }
  110. // Quorum: this tx needs to be applied as if we were not a party
  111. msg = msg.WithEmptyPrivateData(privateStateRepo.IsMPS() && tx.IsPrivate())
  112. // the same transaction object is used for multiple executions (clear the privacy metadata - it should be updated after privacyManager.receive)
  113. // when running in parallel for multiple private states is implemented - a copy of the tx may be used
  114. tx.SetTxPrivacyMetadata(nil)
  115. txContext := NewEVMTxContext(msg)
  116. vmenv := vm.NewEVM(blockContext, txContext, statedb, privateStateDBToUse, p.config, cfg)
  117. vmenv.SetCurrentTX(tx)
  118. receipt, privateReceipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, privateStateDB, header, tx, usedGas, vmenv, cfg, privateStateRepo.IsMPS(), privateStateRepo)
  119. if err != nil {
  120. return nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
  121. }
  122. receipts = append(receipts, receipt)
  123. allLogs = append(allLogs, receipt.Logs...)
  124. // if the private receipt is nil this means the tx was public
  125. // and we do not need to apply the additional logic.
  126. if privateReceipt != nil {
  127. newPrivateReceipt, privateLogs := HandlePrivateReceipt(receipt, privateReceipt, mpsReceipt, tx, privateStateDB, privateStateRepo, p.bc)
  128. privateReceipts = append(privateReceipts, newPrivateReceipt)
  129. allLogs = append(allLogs, privateLogs...)
  130. }
  131. }
  132. // Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
  133. p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles())
  134. return receipts, privateReceipts, allLogs, *usedGas, nil
  135. }
  136. // Quorum
  137. func HandlePrivateReceipt(receipt *types.Receipt, privateReceipt *types.Receipt, mpsReceipt *types.Receipt, tx *types.Transaction, privateStateDB *state.StateDB, privateStateRepo mps.PrivateStateRepository, bc *BlockChain) (*types.Receipt, []*types.Log) {
  138. var (
  139. privateLogs []*types.Log
  140. )
  141. if tx.IsPrivacyMarker() {
  142. // This was a public privacy marker transaction, so we need to handle two scenarios:
  143. // 1) MPS: privateReceipt is an auxiliary MPS receipt which contains actual private receipts in PSReceipts[]
  144. // 2) non-MPS: privateReceipt is the actual receipt for the inner private transaction
  145. // In both cases we return a receipt for the public PMT, which holds the private receipt(s) in PSReceipts[],
  146. // and we then discard the privateReceipt.
  147. if privateStateRepo != nil && privateStateRepo.IsMPS() {
  148. receipt.PSReceipts = privateReceipt.PSReceipts
  149. privateLogs = append(privateLogs, privateReceipt.Logs...)
  150. } else {
  151. receipt.PSReceipts = make(map[types.PrivateStateIdentifier]*types.Receipt)
  152. receipt.PSReceipts[privateStateRepo.DefaultStateMetadata().ID] = privateReceipt
  153. privateLogs = append(privateLogs, privateReceipt.Logs...)
  154. bc.CheckAndSetPrivateState(privateReceipt.Logs, privateStateDB, privateStateRepo.DefaultStateMetadata().ID)
  155. }
  156. // There should be no auxiliary receipt from MPS execution, just logging in case this ever occurs
  157. if mpsReceipt != nil {
  158. log.Error("Unexpected MPS auxiliary receipt, when processing a privacy marker transaction")
  159. }
  160. return privateReceipt, privateLogs
  161. } else {
  162. // This was a regular private transaction.
  163. privateLogs = append(privateLogs, privateReceipt.Logs...)
  164. bc.CheckAndSetPrivateState(privateReceipt.Logs, privateStateDB, privateStateRepo.DefaultStateMetadata().ID)
  165. // handling the auxiliary receipt from MPS execution
  166. if mpsReceipt != nil {
  167. privateReceipt.PSReceipts = mpsReceipt.PSReceipts
  168. privateLogs = append(privateLogs, mpsReceipt.Logs...)
  169. }
  170. return privateReceipt, privateLogs
  171. }
  172. }
  173. // Quorum
  174. // returns the privateStateDB to be used for a transaction
  175. func PrivateStateDBForTxn(isQuorum bool, tx *types.Transaction, stateDb, privateStateDB *state.StateDB) *state.StateDB {
  176. if isQuorum && (tx.IsPrivate() || tx.IsPrivacyMarker()) {
  177. return privateStateDB
  178. }
  179. return stateDb
  180. }
  181. // Quorum
  182. // handling MPS scenario for a private transaction
  183. //
  184. // handleMPS returns the auxiliary receipt and not the standard receipt
  185. func handleMPS(ti int, tx *types.Transaction, gp *GasPool, usedGas *uint64, cfg vm.Config, statedb *state.StateDB, privateStateRepo mps.PrivateStateRepository, config *params.ChainConfig, bc ChainContext, header *types.Header, applyOnPartiesOnly bool, isInnerPrivateTxn bool) (mpsReceipt *types.Receipt, err error) {
  186. if tx.IsPrivate() && privateStateRepo != nil && privateStateRepo.IsMPS() {
  187. publicStateDBFactory := func() *state.StateDB {
  188. db := statedb.Copy()
  189. db.Prepare(tx.Hash(), header.Hash(), ti)
  190. return db
  191. }
  192. privateStateDBFactory := func(psi types.PrivateStateIdentifier) (*state.StateDB, error) {
  193. db, err := privateStateRepo.StatePSI(psi)
  194. if err != nil {
  195. return nil, err
  196. }
  197. db.Prepare(tx.Hash(), header.Hash(), ti)
  198. return db, nil
  199. }
  200. mpsReceipt, err = ApplyTransactionOnMPS(config, bc, nil, gp, publicStateDBFactory, privateStateDBFactory, header, tx, usedGas, cfg, privateStateRepo, applyOnPartiesOnly, isInnerPrivateTxn)
  201. }
  202. return
  203. }
  204. // Quorum
  205. // ApplyTransactionOnMPS runs the transaction on multiple private states which
  206. // the transaction is designated to.
  207. //
  208. // For each designated private state, the transaction is ran only ONCE.
  209. //
  210. // ApplyTransactionOnMPS returns the auxiliary receipt which is mainly used to capture
  211. // multiple private receipts and logs array. Logs are decorated with types.PrivateStateIdentifier
  212. //
  213. // The originalGP gas pool will not be modified
  214. func ApplyTransactionOnMPS(config *params.ChainConfig, bc ChainContext, author *common.Address, originalGP *GasPool,
  215. publicStateDBFactory func() *state.StateDB, privateStateDBFactory func(psi types.PrivateStateIdentifier) (*state.StateDB, error),
  216. header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, privateStateRepo mps.PrivateStateRepository,
  217. applyOnPartiesOnly bool, isInnerPrivateTxn bool) (*types.Receipt, error) {
  218. mpsReceipt := &types.Receipt{
  219. QuorumReceiptExtraData: types.QuorumReceiptExtraData{
  220. PSReceipts: make(map[types.PrivateStateIdentifier]*types.Receipt),
  221. },
  222. Logs: make([]*types.Log, 0),
  223. }
  224. _, managedParties, _, _, err := private.P.Receive(common.BytesToEncryptedPayloadHash(tx.Data()))
  225. if err != nil {
  226. return nil, err
  227. }
  228. targetPsi := make(map[types.PrivateStateIdentifier]struct{})
  229. for _, managedParty := range managedParties {
  230. psMetadata, err := bc.PrivateStateManager().ResolveForManagedParty(managedParty)
  231. if err != nil {
  232. return nil, err
  233. }
  234. targetPsi[psMetadata.ID] = struct{}{}
  235. }
  236. // execute in all the managed private states
  237. // TODO this could be enhanced to run in parallel
  238. for _, psi := range bc.PrivateStateManager().PSIs() {
  239. if cfg.ApplyOnPartyOverride != nil && *cfg.ApplyOnPartyOverride != psi {
  240. continue
  241. }
  242. _, applyAsParty := targetPsi[psi]
  243. if !applyAsParty && applyOnPartiesOnly {
  244. continue
  245. }
  246. privateStateDB, err := privateStateDBFactory(psi)
  247. if err != nil {
  248. return nil, err
  249. }
  250. publicStateDB := publicStateDBFactory()
  251. // use a clone of the gas pool (as we don't want to consume gas multiple times for each MPS execution, which might blow the block gasLimit on MPS node)
  252. gp := new(GasPool).AddGas(originalGP.Gas())
  253. _, privateReceipt, err := ApplyTransaction(config, bc, author, gp, publicStateDB, privateStateDB, header, tx, usedGas, cfg, !applyAsParty, privateStateRepo, isInnerPrivateTxn)
  254. if err != nil {
  255. return nil, err
  256. }
  257. // set the PSI for each log (so that the filter system knows for what private state they are)
  258. // we don't care about the empty privateReceipt (as we'll execute the transaction on the empty state anyway)
  259. if applyAsParty {
  260. for _, log := range privateReceipt.Logs {
  261. log.PSI = psi
  262. mpsReceipt.Logs = append(mpsReceipt.Logs, log)
  263. }
  264. mpsReceipt.PSReceipts[psi] = privateReceipt
  265. bc.CheckAndSetPrivateState(privateReceipt.Logs, privateStateDB, psi)
  266. }
  267. }
  268. return mpsReceipt, nil
  269. }
  270. // /Quorum
  271. func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb, privateStateDB *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, cfg vm.Config, forceNonParty bool, privateStateRepo mps.PrivateStateRepository) (*types.Receipt, *types.Receipt, error) {
  272. // Create a new context to be used in the EVM environment.
  273. // Quorum
  274. txIndex := statedb.TxIndex()
  275. evm.InnerApply = func(innerTx *types.Transaction) error {
  276. return ApplyInnerTransaction(bc, author, gp, statedb, privateStateDB, header, tx, usedGas, cfg, forceNonParty, privateStateRepo, evm, innerTx, txIndex)
  277. }
  278. // End Quorum
  279. // Apply the transaction to the current state (included in the env)
  280. result, err := ApplyMessage(evm, msg, gp)
  281. if err != nil {
  282. return nil, nil, err
  283. }
  284. // Update the state with pending changes.
  285. var root []byte
  286. if config.IsByzantium(header.Number) {
  287. statedb.Finalise(true)
  288. } else {
  289. root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
  290. }
  291. *usedGas += result.UsedGas
  292. // Create a new receipt for the transaction, storing the intermediate root and gas used
  293. // by the tx.
  294. receipt := &types.Receipt{Type: tx.Type(), PostState: common.CopyBytes(root), CumulativeGasUsed: *usedGas}
  295. // If this is a private transaction, the public receipt should always
  296. // indicate success.
  297. if !(config.IsQuorum && tx.IsPrivate()) && result.Failed() {
  298. receipt.Status = types.ReceiptStatusFailed
  299. } else {
  300. receipt.Status = types.ReceiptStatusSuccessful
  301. }
  302. receipt.TxHash = tx.Hash()
  303. receipt.GasUsed = result.UsedGas
  304. // If the transaction created a contract, store the creation address in the receipt.
  305. if msg.To() == nil {
  306. receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
  307. }
  308. // Set the receipt logs and create the bloom filter.
  309. receipt.Logs = statedb.GetLogs(tx.Hash())
  310. receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
  311. receipt.BlockHash = statedb.BlockHash()
  312. receipt.BlockNumber = header.Number
  313. receipt.TransactionIndex = uint(statedb.TxIndex())
  314. // Quorum
  315. var privateReceipt *types.Receipt
  316. if config.IsQuorum {
  317. if tx.IsPrivate() {
  318. var privateRoot []byte
  319. if config.IsByzantium(header.Number) {
  320. privateStateDB.Finalise(true)
  321. } else {
  322. privateRoot = privateStateDB.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
  323. }
  324. privateReceipt = types.NewReceipt(privateRoot, result.Failed(), *usedGas)
  325. privateReceipt.TxHash = tx.Hash()
  326. privateReceipt.GasUsed = result.UsedGas
  327. if msg.To() == nil {
  328. privateReceipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
  329. }
  330. privateReceipt.Logs = privateStateDB.GetLogs(tx.Hash())
  331. privateReceipt.Bloom = types.CreateBloom(types.Receipts{privateReceipt})
  332. } else {
  333. // This may have been a privacy marker transaction, in which case need to retrieve the receipt for the
  334. // inner private transaction (note that this can be an mpsReceipt, containing private receipts in PSReceipts).
  335. if evm.InnerPrivateReceipt != nil {
  336. privateReceipt = evm.InnerPrivateReceipt
  337. }
  338. }
  339. }
  340. // Save revert reason if feature enabled
  341. if bc != nil && bc.QuorumConfig().RevertReasonEnabled() {
  342. revertReason := result.Revert()
  343. if revertReason != nil {
  344. if config.IsQuorum && tx.IsPrivate() {
  345. privateReceipt.RevertReason = revertReason
  346. } else {
  347. receipt.RevertReason = revertReason
  348. }
  349. }
  350. }
  351. // End Quorum
  352. return receipt, privateReceipt, err
  353. }
  354. // ApplyTransaction attempts to apply a transaction to the given state database
  355. // and uses the input parameters for its environment. It returns the receipt
  356. // for the transaction, gas used and an error if the transaction failed,
  357. // indicating the block was invalid.
  358. func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb, privateStateDB *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, forceNonParty bool, privateStateRepo mps.PrivateStateRepository, isInnerPrivateTxn bool) (*types.Receipt, *types.Receipt, error) {
  359. // Quorum - decide the privateStateDB to use
  360. privateStateDbToUse := PrivateStateDBForTxn(config.IsQuorum, tx, statedb, privateStateDB)
  361. // End Quorum
  362. // Quorum - check for account permissions to execute the transaction
  363. if core.IsV2Permission() {
  364. if err := core.CheckAccountPermission(tx.From(), tx.To(), tx.Value(), tx.Data(), tx.Gas(), tx.GasPrice()); err != nil {
  365. return nil, nil, err
  366. }
  367. }
  368. if config.IsQuorum && !config.IsGasPriceEnabled(header.Number) && tx.GasPrice() != nil && tx.GasPrice().Cmp(common.Big0) > 0 {
  369. return nil, nil, ErrInvalidGasPrice
  370. }
  371. msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
  372. if err != nil {
  373. return nil, nil, err
  374. }
  375. // Quorum: this tx needs to be applied as if we were not a party
  376. msg = msg.WithEmptyPrivateData(forceNonParty && tx.IsPrivate())
  377. // Quorum: if this is the inner private txn of a PMT then need to indicate this
  378. msg = msg.WithInnerPrivateFlag(isInnerPrivateTxn)
  379. // Create a new context to be used in the EVM environment
  380. blockContext := NewEVMBlockContext(header, bc, author)
  381. txContext := NewEVMTxContext(msg)
  382. vmenv := vm.NewEVM(blockContext, txContext, statedb, privateStateDbToUse, config, cfg)
  383. // the same transaction object is used for multiple executions (clear the privacy metadata - it should be updated after privacyManager.receive)
  384. // when running in parallel for multiple private states is implemented - a copy of the tx may be used
  385. tx.SetTxPrivacyMetadata(nil)
  386. vmenv.SetCurrentTX(tx)
  387. return applyTransaction(msg, config, bc, author, gp, statedb, privateStateDB, header, tx, usedGas, vmenv, cfg, forceNonParty, privateStateRepo)
  388. }
  389. // Quorum
  390. // ApplyInnerTransaction is called from within the Quorum precompile for privacy marker transactions.
  391. // It's a call back which essentially duplicates the logic in Process(),
  392. // in this case to process the actual private transaction.
  393. func ApplyInnerTransaction(bc ChainContext, author *common.Address, gp *GasPool, stateDB *state.StateDB, privateStateDB *state.StateDB, header *types.Header, outerTx *types.Transaction, usedGas *uint64, evmConf vm.Config, forceNonParty bool, privateStateRepo mps.PrivateStateRepository, vmenv *vm.EVM, innerTx *types.Transaction, txIndex int) error {
  394. // this should never happen, but added as sanity check
  395. if !innerTx.IsPrivate() {
  396. return errors.New("attempt to process non-private transaction from within ApplyInnerTransaction()")
  397. }
  398. // create a single use gas pool (as we don't want the gas consumed by the inner tx to blow the block gasLimit on a participant node)
  399. singleUseGasPool := new(GasPool).AddGas(innerTx.Gas())
  400. if privateStateRepo != nil && privateStateRepo.IsMPS() {
  401. mpsReceipt, err := handleMPS(txIndex, innerTx, singleUseGasPool, usedGas, evmConf, stateDB, privateStateRepo, bc.Config(), bc, header, true, true)
  402. if err != nil {
  403. return err
  404. }
  405. // Store the auxiliary MPS receipt for the inner private transaction (this contains private receipts in PSReceipts).
  406. vmenv.InnerPrivateReceipt = mpsReceipt
  407. return nil
  408. }
  409. defer prepareStates(outerTx, stateDB, privateStateDB, txIndex)
  410. prepareStates(innerTx, stateDB, privateStateDB, txIndex)
  411. used := uint64(0)
  412. _, innerPrivateReceipt, err := ApplyTransaction(bc.Config(), bc, author, singleUseGasPool, stateDB, privateStateDB, header, innerTx, &used, evmConf, forceNonParty, privateStateRepo, true)
  413. if err != nil {
  414. return err
  415. }
  416. if innerPrivateReceipt != nil {
  417. if innerPrivateReceipt.Logs == nil {
  418. innerPrivateReceipt.Logs = make([]*types.Log, 0)
  419. }
  420. // Store the receipt for the inner private transaction.
  421. innerPrivateReceipt.TxHash = innerTx.Hash()
  422. vmenv.InnerPrivateReceipt = innerPrivateReceipt
  423. }
  424. return nil
  425. }
  426. // Quorum
  427. func prepareStates(tx *types.Transaction, stateDB *state.StateDB, privateStateDB *state.StateDB, txIndex int) {
  428. stateDB.Prepare(tx.Hash(), stateDB.BlockHash(), txIndex)
  429. privateStateDB.Prepare(tx.Hash(), privateStateDB.BlockHash(), txIndex)
  430. }