contracts_quorum.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2014 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 vm
  17. import (
  18. "errors"
  19. "github.com/ethereum/go-ethereum/common"
  20. "github.com/ethereum/go-ethereum/core/types"
  21. "github.com/ethereum/go-ethereum/log"
  22. "github.com/ethereum/go-ethereum/private"
  23. )
  24. // QuorumPrecompiledContract is an extended interface for native Quorum Go contracts. The implementation
  25. // requires a deterministic gas count based on the input size of the Run method of the
  26. // contract.
  27. type QuorumPrecompiledContract interface {
  28. RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
  29. Run(evm *EVM, input []byte) ([]byte, error) // Run runs the precompiled contract
  30. }
  31. // QuorumPrecompiledContracts is the default set of pre-compiled Quorum contracts (with an extended interface).
  32. var QuorumPrecompiledContracts = map[common.Address]QuorumPrecompiledContract{
  33. common.QuorumPrivacyPrecompileContractAddress(): &privacyMarker{},
  34. }
  35. // RunQuorumPrecompiledContract runs and evaluates the output of an extended precompiled contract.
  36. // It returns
  37. // - the returned bytes,
  38. // - the _remaining_ gas,
  39. // - any error that occurred
  40. func RunQuorumPrecompiledContract(evm *EVM, p QuorumPrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
  41. gasCost := p.RequiredGas(input)
  42. if suppliedGas < gasCost {
  43. return nil, 0, ErrOutOfGas
  44. }
  45. suppliedGas -= gasCost
  46. output, err := p.Run(evm, input)
  47. return output, suppliedGas, err
  48. }
  49. type privacyMarker struct{}
  50. func (c *privacyMarker) RequiredGas(_ []byte) uint64 {
  51. return uint64(0)
  52. }
  53. // privacyMarker precompile execution
  54. // Retrieves private transaction from Tessera and executes it.
  55. // If we are not a participant, then just ensure public state remains in sync.
  56. // input = 20 byte address of sender, 64 byte hash for the private transaction
  57. func (c *privacyMarker) Run(evm *EVM, _ []byte) ([]byte, error) {
  58. log.Debug("Running privacy marker precompile")
  59. // support vanilla ethereum tests where tx is not set
  60. if evm.currentTx == nil {
  61. return nil, nil
  62. }
  63. logger := log.New("pmtHash", evm.currentTx.Hash())
  64. if evm.depth != 0 || !evm.currentTx.IsPrivacyMarker() {
  65. // only supporting direct precompile calls so far
  66. logger.Warn("Invalid privacy marker precompile execution")
  67. return nil, nil
  68. }
  69. if evm.currentTx.IsPrivate() {
  70. //only public transactions can call the precompile
  71. logger.Warn("PMT is not a public transaction")
  72. return nil, nil
  73. }
  74. tx, _, _, err := private.FetchPrivateTransaction(evm.currentTx.Data())
  75. if err != nil {
  76. logger.Error("Failed to retrieve inner transaction from private transaction manager", "err", err)
  77. return nil, nil
  78. }
  79. if tx == nil {
  80. logger.Debug("Not a participant, skipping execution")
  81. return nil, nil
  82. }
  83. if !tx.IsPrivate() {
  84. //should only allow private txns from inside precompile, as many assumptions
  85. //about how a tx operates are based on its privacy (e.g. which dbs to use, PE checks etc)
  86. logger.Warn("Inner transaction retrieved from private transaction manager is not a private transaction, skipping execution")
  87. return nil, nil
  88. }
  89. //validate the private tx is signed, and that it's the same signer as the PMT
  90. signedBy := tx.From()
  91. if signedBy.Hex() == (common.Address{}).Hex() || signedBy.Hex() != evm.currentTx.From().Hex() {
  92. logger.Warn("PMT and inner private transaction have different signers, skipping execution")
  93. return nil, nil
  94. }
  95. // validate the private tx has the same nonce as the PMT
  96. if tx.Nonce() != evm.currentTx.Nonce() {
  97. logger.Warn("PMT and inner private transaction have different nonces, skipping execution")
  98. return nil, nil
  99. }
  100. if err := applyTransactionWithoutIncrementingNonce(evm, tx); err != nil {
  101. logger.Warn("Unable to apply PMT's inner transaction to EVM, skipping execution", "err", err)
  102. return nil, nil
  103. }
  104. logger.Debug("Inner private transaction applied")
  105. return nil, nil
  106. }
  107. // Effectively execute the internal private transaction without incrementing the nonce of the sender account.
  108. // (1) make a copy of the sender's starting (i.e. current) account nonce.
  109. // (2) decrement the sender's account nonce in the public state so that the internal private transaction (which has the same 'from' and 'nonce' as the outer PMT) can be executed.
  110. // (3a) execute the internal private transaction.
  111. // (3b) if the internal private tx is successfully executed then the sender's account nonce will be incremented back to the starting nonce.
  112. // (3c) if the execution was unsuccessful then the nonce may not be incremented.
  113. // (4) force reset the nonce to the starting value in any case.
  114. func applyTransactionWithoutIncrementingNonce(evm *EVM, tx *types.Transaction) error {
  115. if evm.InnerApply == nil {
  116. return errors.New("nil inner apply function")
  117. }
  118. fromAddr := evm.currentTx.From()
  119. startingNonce := evm.PublicState().GetNonce(fromAddr)
  120. evm.publicState.SetNonce(fromAddr, startingNonce-1)
  121. defer evm.publicState.SetNonce(fromAddr, startingNonce)
  122. return evm.InnerApply(tx)
  123. }