github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/consensus/bor/statefull/processor.go (about) 1 package statefull 2 3 import ( 4 "context" 5 "math" 6 "math/big" 7 8 ethereum "github.com/ethereum/go-ethereum" 9 "github.com/ethereum/go-ethereum/common" 10 "github.com/ethereum/go-ethereum/consensus" 11 "github.com/ethereum/go-ethereum/core" 12 "github.com/ethereum/go-ethereum/core/state" 13 "github.com/ethereum/go-ethereum/core/types" 14 "github.com/ethereum/go-ethereum/core/vm" 15 "github.com/ethereum/go-ethereum/params" 16 ) 17 18 var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") 19 20 type ChainContext struct { 21 Chain consensus.ChainHeaderReader 22 Bor consensus.Engine 23 } 24 25 func (c ChainContext) Engine() consensus.Engine { 26 return c.Bor 27 } 28 29 func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header { 30 return c.Chain.GetHeader(hash, number) 31 } 32 33 // callmsg implements core.Message to allow passing it as a transaction simulator. 34 type Callmsg struct { 35 ethereum.CallMsg 36 } 37 38 func (m Callmsg) From() common.Address { return m.CallMsg.From } 39 func (m Callmsg) Nonce() uint64 { return 0 } 40 func (m Callmsg) CheckNonce() bool { return false } 41 func (m Callmsg) To() *common.Address { return m.CallMsg.To } 42 func (m Callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } 43 func (m Callmsg) Gas() uint64 { return m.CallMsg.Gas } 44 func (m Callmsg) Value() *big.Int { return m.CallMsg.Value } 45 func (m Callmsg) Data() []byte { return m.CallMsg.Data } 46 47 // get system message 48 func GetSystemMessage(toAddress common.Address, data []byte) Callmsg { 49 return Callmsg{ 50 ethereum.CallMsg{ 51 From: systemAddress, 52 Gas: math.MaxUint64 / 2, 53 GasPrice: big.NewInt(0), 54 Value: big.NewInt(0), 55 To: &toAddress, 56 Data: data, 57 }, 58 } 59 } 60 61 // apply message 62 func ApplyMessage( 63 _ context.Context, 64 msg Callmsg, 65 state *state.StateDB, 66 header *types.Header, 67 chainConfig *params.ChainConfig, 68 chainContext core.ChainContext, 69 ) (uint64, error) { 70 initialGas := msg.Gas() 71 72 // Create a new context to be used in the EVM environment 73 blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase) 74 75 // Create a new environment which holds all relevant information 76 // about the transaction and calling mechanisms. 77 vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{}) 78 79 // Apply the transaction to the current state (included in the env) 80 _, gasLeft, err := vmenv.Call( 81 vm.AccountRef(msg.From()), 82 *msg.To(), 83 msg.Data(), 84 msg.Gas(), 85 msg.Value(), 86 nil, 87 ) 88 // Update the state with pending changes 89 if err != nil { 90 state.Finalise(true) 91 } 92 93 gasUsed := initialGas - gasLeft 94 95 return gasUsed, nil 96 } 97 98 func ApplyBorMessage(vmenv vm.EVM, msg Callmsg) (*core.ExecutionResult, error) { 99 initialGas := msg.Gas() 100 101 // Apply the transaction to the current state (included in the env) 102 ret, gasLeft, err := vmenv.Call( 103 vm.AccountRef(msg.From()), 104 *msg.To(), 105 msg.Data(), 106 msg.Gas(), 107 msg.Value(), 108 nil, 109 ) 110 // Update the state with pending changes 111 if err != nil { 112 vmenv.StateDB.Finalise(true) 113 } 114 115 gasUsed := initialGas - gasLeft 116 117 return &core.ExecutionResult{ 118 UsedGas: gasUsed, 119 Err: err, 120 ReturnData: ret, 121 }, nil 122 }