github.com/ethereum/go-ethereum@v1.16.1/core/stateless.go (about)

     1  // Copyright 2024 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 core
    18  
    19  import (
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/common/lru"
    22  	"github.com/ethereum/go-ethereum/consensus/beacon"
    23  	"github.com/ethereum/go-ethereum/consensus/ethash"
    24  	"github.com/ethereum/go-ethereum/core/state"
    25  	"github.com/ethereum/go-ethereum/core/stateless"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/core/vm"
    28  	"github.com/ethereum/go-ethereum/log"
    29  	"github.com/ethereum/go-ethereum/params"
    30  	"github.com/ethereum/go-ethereum/trie"
    31  	"github.com/ethereum/go-ethereum/triedb"
    32  )
    33  
    34  // ExecuteStateless runs a stateless execution based on a witness, verifies
    35  // everything it can locally and returns the state root and receipt root, that
    36  // need the other side to explicitly check.
    37  //
    38  // This method is a bit of a sore thumb here, but:
    39  //   - It cannot be placed in core/stateless, because state.New prodces a circular dep
    40  //   - It cannot be placed outside of core, because it needs to construct a dud headerchain
    41  //
    42  // TODO(karalabe): Would be nice to resolve both issues above somehow and move it.
    43  func ExecuteStateless(config *params.ChainConfig, vmconfig vm.Config, block *types.Block, witness *stateless.Witness) (common.Hash, common.Hash, error) {
    44  	// Sanity check if the supplied block accidentally contains a set root or
    45  	// receipt hash. If so, be very loud, but still continue.
    46  	if block.Root() != (common.Hash{}) {
    47  		log.Error("stateless runner received state root it's expected to calculate (faulty consensus client)", "block", block.Number())
    48  	}
    49  	if block.ReceiptHash() != (common.Hash{}) {
    50  		log.Error("stateless runner received receipt root it's expected to calculate (faulty consensus client)", "block", block.Number())
    51  	}
    52  	// Create and populate the state database to serve as the stateless backend
    53  	memdb := witness.MakeHashDB()
    54  	db, err := state.New(witness.Root(), state.NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), nil))
    55  	if err != nil {
    56  		return common.Hash{}, common.Hash{}, err
    57  	}
    58  	// Create a blockchain that is idle, but can be used to access headers through
    59  	chain := &HeaderChain{
    60  		config:      config,
    61  		chainDb:     memdb,
    62  		headerCache: lru.NewCache[common.Hash, *types.Header](256),
    63  		engine:      beacon.New(ethash.NewFaker()),
    64  	}
    65  	processor := NewStateProcessor(config, chain)
    66  	validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block
    67  
    68  	// Run the stateless blocks processing and self-validate certain fields
    69  	res, err := processor.Process(block, db, vmconfig)
    70  	if err != nil {
    71  		return common.Hash{}, common.Hash{}, err
    72  	}
    73  	if err = validator.ValidateState(block, db, res, true); err != nil {
    74  		return common.Hash{}, common.Hash{}, err
    75  	}
    76  	// Almost everything validated, but receipt and state root needs to be returned
    77  	receiptRoot := types.DeriveSha(res.Receipts, trie.NewStackTrie(nil))
    78  	stateRoot := db.IntermediateRoot(config.IsEIP158(block.Number()))
    79  	return stateRoot, receiptRoot, nil
    80  }