ApplyTransaction attempts to apply a transaction to the given state database and uses the input parameters for its environment. It returns the receipt for the transaction, gas used and an error if the transaction failed, indicating the block was invalid.
(config *configs.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, pubStateDb *state.StateDB, privateStateDb *state.StateDB, remoteDB database.RemoteDatabase, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, accm *accounts.Manager)
| 111 | // for the transaction, gas used and an error if the transaction failed, |
| 112 | // indicating the block was invalid. |
| 113 | func ApplyTransaction(config *configs.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, pubStateDb *state.StateDB, |
| 114 | privateStateDb *state.StateDB, remoteDB database.RemoteDatabase, header *types.Header, tx *types.Transaction, usedGas *uint64, |
| 115 | cfg vm.Config, accm *accounts.Manager) (*types.Receipt, *types.Receipt, uint64, error) { |
| 116 | msg, err := tx.AsMessage(types.MakeSigner(config)) |
| 117 | if err != nil { |
| 118 | return nil, nil, 0, err |
| 119 | } |
| 120 | |
| 121 | // if the tx type is not supported, return early |
| 122 | if !types.SupportTxType(tx.Type()) { |
| 123 | return nil, nil, 0, types.ErrNotSupportedTxType |
| 124 | } |
| 125 | |
| 126 | // this is for sanitize, may be useful later. for now, its useless because it already returned |
| 127 | if !tx.IsBasic() { |
| 128 | msg.SetData([]byte{}) |
| 129 | } |
| 130 | |
| 131 | // Create a new context to be used in the EVM environment |
| 132 | context := NewEVMContext(msg, header, bc, author) |
| 133 | // Create a new environment which holds all relevant information |
| 134 | // about the transaction and calling mechanisms. |
| 135 | vmenv := vm.NewEVM(context, pubStateDb, config, cfg) |
| 136 | // Apply the transaction to the current state (included in the env) |
| 137 | _, gas, failed, err := ApplyMessage(vmenv, msg, gp) |
| 138 | if err != nil { |
| 139 | return nil, nil, 0, err |
| 140 | } |
| 141 | pubStateDb.Finalise(true) |
| 142 | *usedGas += gas |
| 143 | |
| 144 | // Create a new pubReceipt for the transaction, storing the intermediate root and gas used by the tx |
| 145 | // based on the eip phase, we're passing whether the root touch-delete accounts. |
| 146 | pubReceipt := types.NewReceipt([]byte{}, failed, *usedGas) |
| 147 | pubReceipt.TxHash = tx.Hash() |
| 148 | pubReceipt.GasUsed = gas |
| 149 | // if the transaction created a contract, store the creation address in the pubReceipt. |
| 150 | if msg.To() == nil { |
| 151 | pubReceipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) |
| 152 | } |
| 153 | // Set the pubReceipt logs and create a bloom for filtering |
| 154 | pubReceipt.Logs = pubStateDb.GetLogs(tx.Hash()) |
| 155 | pubReceipt.Bloom = types.CreateBloom(types.Receipts{pubReceipt}) |
| 156 | |
| 157 | var privReceipt *types.Receipt |
| 158 | // For private tx, it should process its real private tx payload in participant's node. If account manager is nil, |
| 159 | // doesn't process private tx. If the node does not support private transaction, skip it. |
| 160 | if tx.IsPrivate() && accm != nil && types.SupportTxType(tx.Type()) { |
| 161 | |
| 162 | // for now, it's impossible to enter here |
| 163 | privReceipt, err = tryApplyPrivateTx(config, bc, author, gp, privateStateDb, remoteDB, header, tx, cfg, accm) |
| 164 | if err != nil { |
| 165 | if err == NoPermissionError { |
| 166 | log.Info("No permission to process the transaction.") |
| 167 | return pubReceipt, privReceipt, gas, nil |
| 168 | } else { |
| 169 | log.Error("Cannot process the transaction.", err) |
| 170 | return pubReceipt, privReceipt, 0, err |
no test coverage detected