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  }