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