github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/blockproc/evmmodule/evm.go (about)

     1  package evmmodule
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  
     7  	"github.com/unicornultrafoundation/go-u2u/common"
     8  	"github.com/unicornultrafoundation/go-u2u/core/state"
     9  	"github.com/unicornultrafoundation/go-u2u/core/types"
    10  	"github.com/unicornultrafoundation/go-u2u/log"
    11  	"github.com/unicornultrafoundation/go-u2u/params"
    12  
    13  	"github.com/unicornultrafoundation/go-u2u/evmcore"
    14  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc"
    15  	"github.com/unicornultrafoundation/go-u2u/native"
    16  	"github.com/unicornultrafoundation/go-u2u/native/iblockproc"
    17  	"github.com/unicornultrafoundation/go-u2u/u2u"
    18  	"github.com/unicornultrafoundation/go-u2u/utils"
    19  )
    20  
    21  type EVMModule struct{}
    22  
    23  func New() *EVMModule {
    24  	return &EVMModule{}
    25  }
    26  
    27  func (p *EVMModule) Start(block iblockproc.BlockCtx, statedb *state.StateDB, reader evmcore.DummyChain, onNewLog func(*types.Log), net u2u.Rules, evmCfg *params.ChainConfig) blockproc.EVMProcessor {
    28  	var prevBlockHash common.Hash
    29  	if block.Idx != 0 {
    30  		prevBlockHash = reader.GetHeader(common.Hash{}, uint64(block.Idx-1)).Hash
    31  	}
    32  	return &U2UEVMProcessor{
    33  		block:         block,
    34  		reader:        reader,
    35  		statedb:       statedb,
    36  		onNewLog:      onNewLog,
    37  		net:           net,
    38  		evmCfg:        evmCfg,
    39  		blockIdx:      utils.U64toBig(uint64(block.Idx)),
    40  		prevBlockHash: prevBlockHash,
    41  	}
    42  }
    43  
    44  type U2UEVMProcessor struct {
    45  	block    iblockproc.BlockCtx
    46  	reader   evmcore.DummyChain
    47  	statedb  *state.StateDB
    48  	onNewLog func(*types.Log)
    49  	net      u2u.Rules
    50  	evmCfg   *params.ChainConfig
    51  
    52  	blockIdx      *big.Int
    53  	prevBlockHash common.Hash
    54  
    55  	gasUsed uint64
    56  
    57  	incomingTxs types.Transactions
    58  	skippedTxs  []uint32
    59  	receipts    types.Receipts
    60  }
    61  
    62  func (p *U2UEVMProcessor) evmBlockWith(txs types.Transactions) *evmcore.EvmBlock {
    63  	baseFee := p.net.Economy.MinGasPrice
    64  	if !p.net.Upgrades.London {
    65  		baseFee = nil
    66  	}
    67  	h := &evmcore.EvmHeader{
    68  		Number:     p.blockIdx,
    69  		Hash:       common.Hash(p.block.Atropos),
    70  		ParentHash: p.prevBlockHash,
    71  		Root:       common.Hash{},
    72  		Time:       p.block.Time,
    73  		Coinbase:   common.Address{},
    74  		GasLimit:   math.MaxUint64,
    75  		GasUsed:    p.gasUsed,
    76  		BaseFee:    baseFee,
    77  	}
    78  
    79  	return evmcore.NewEvmBlock(h, txs)
    80  }
    81  
    82  func (p *U2UEVMProcessor) Execute(txs types.Transactions) types.Receipts {
    83  	evmProcessor := evmcore.NewStateProcessor(p.evmCfg, p.reader)
    84  	txsOffset := uint(len(p.incomingTxs))
    85  
    86  	// Process txs
    87  	evmBlock := p.evmBlockWith(txs)
    88  	receipts, _, skipped, err := evmProcessor.Process(evmBlock, p.statedb, u2u.DefaultVMConfig, &p.gasUsed, func(l *types.Log, _ *state.StateDB) {
    89  		// Note: l.Index is properly set before
    90  		l.TxIndex += txsOffset
    91  		p.onNewLog(l)
    92  	})
    93  	if err != nil {
    94  		log.Crit("EVM internal error", "err", err)
    95  	}
    96  
    97  	if txsOffset > 0 {
    98  		for i, n := range skipped {
    99  			skipped[i] = n + uint32(txsOffset)
   100  		}
   101  		for _, r := range receipts {
   102  			r.TransactionIndex += txsOffset
   103  		}
   104  	}
   105  
   106  	p.incomingTxs = append(p.incomingTxs, txs...)
   107  	p.skippedTxs = append(p.skippedTxs, skipped...)
   108  	p.receipts = append(p.receipts, receipts...)
   109  
   110  	return receipts
   111  }
   112  
   113  func (p *U2UEVMProcessor) Finalize() (evmBlock *evmcore.EvmBlock, skippedTxs []uint32, receipts types.Receipts) {
   114  	evmBlock = p.evmBlockWith(
   115  		// Filter skipped transactions. Receipts are filtered already
   116  		native.FilterSkippedTxs(p.incomingTxs, p.skippedTxs),
   117  	)
   118  	skippedTxs = p.skippedTxs
   119  	receipts = p.receipts
   120  
   121  	// Get state root
   122  	newStateHash, err := p.statedb.Commit(true)
   123  	if err != nil {
   124  		log.Crit("Failed to commit state", "err", err)
   125  	}
   126  	evmBlock.Root = newStateHash
   127  
   128  	return
   129  }