Skip to content

Commit

Permalink
simplify code by removing all stateless references (ethereum#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
gballet authored Nov 8, 2021
1 parent a132a6d commit f6f8616
Show file tree
Hide file tree
Showing 4 changed files with 1 addition and 168 deletions.
12 changes: 1 addition & 11 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1831,17 +1831,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
receipts types.Receipts
logs []*types.Log
)
if len(block.Header().VerkleProof) == 0 {
receipts, logs, _, usedGas, err = bc.processor.Process(block, statedb, bc.vmConfig)
} else {
var leaves map[common.Hash]common.Hash
leaves, err = trie.DeserializeAndVerifyVerkleProof(block.Header().VerkleProof)
if err != nil {
return it.index, err
}
statedb.SetStateless(leaves)
receipts, logs, usedGas, err = bc.processor.ProcessStateless(block, statedb, bc.vmConfig, leaves)
}
receipts, logs, _, usedGas, err = bc.processor.Process(block, statedb, bc.vmConfig)
if err != nil {
bc.reportBlock(block, receipts, err)
atomic.StoreUint32(&followupInterrupt, 1)
Expand Down
117 changes: 0 additions & 117 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ type StateDB struct {
// Per-transaction access list
accessList *accessList

// Stateless locations for this block
stateless map[common.Hash]common.Hash

// Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot.
journal *journal
Expand Down Expand Up @@ -423,12 +420,6 @@ func (s *StateDB) SetCode(addr common.Address, code []byte) {
}
}

// SetStateless sets the vales recovered from the execution of a stateless
// block.
func (s *StateDB) SetStateless(leaves map[common.Hash]common.Hash) {
s.stateless = leaves
}

func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := s.GetOrNewStateObject(addr)
if stateObject != nil {
Expand Down Expand Up @@ -470,46 +461,6 @@ func (s *StateDB) Suicide(addr common.Address) bool {
// Setting, updating & deleting state object methods.
//

func (s *StateDB) updateStatelessStateObject(obj *stateObject) {
addr := obj.Address()

var (
ok bool
n common.Hash
v common.Hash
b common.Hash
cs common.Hash
ch common.Hash
)

versionKey := common.BytesToHash(trieUtils.GetTreeKeyVersion(addr[:]))
if v, ok = s.stateless[versionKey]; ok {
nonceKey := common.BytesToHash(trieUtils.GetTreeKeyNonce(addr[:]))
if n, ok = s.stateless[nonceKey]; ok {
balanceKey := common.BytesToHash(trieUtils.GetTreeKeyBalance(addr[:]))
if b, ok = s.stateless[balanceKey]; ok {
codeHashKey := common.BytesToHash(trieUtils.GetTreeKeyCodeKeccak(addr[:]))
if _, ok = s.stateless[codeHashKey]; ok {
v[0] = byte(0)
binary.BigEndian.PutUint64(n[:], obj.data.Nonce)
copy(ch[:], obj.data.CodeHash[:])
copy(b[:], obj.data.Balance.Bytes())
binary.BigEndian.PutUint64(cs[:], uint64(len(obj.code)))

// TODO(@gballet) stateless tree update
// i.e. perform a "delta" update on all
// commitments. go-verkle currently has
// no support for these.
}
}
}
}

if !ok {
s.setError(fmt.Errorf("updateStatelessStateObject (%x) missing", addr[:]))
}
}

// updateStateObject writes the given object to the trie.
func (s *StateDB) updateStateObject(obj *stateObject) {
// Track the amount of time wasted on updating the account from the trie
Expand All @@ -519,12 +470,6 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
// Encode the account and update the account trie
addr := obj.Address()

// bypass the snapshot and writing to tree if in stateless mode
if s.stateless != nil {
s.updateStatelessStateObject(obj)
return
}

if err := s.trie.TryUpdateAccount(addr[:], &obj.data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %w", addr[:], err))
}
Expand All @@ -545,21 +490,12 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
}
}

func (s *StateDB) deleteStatelessStateObject(obj *stateObject) {
// unsupported
panic("not currently supported")
}

// deleteStateObject removes the given object from the state trie.
func (s *StateDB) deleteStateObject(obj *stateObject) {
// Track the amount of time wasted on deleting the account from the trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
}
if s.stateless != nil {
s.deleteStatelessStateObject(obj)
return
}

// Delete the account from the trie
if !s.trie.IsVerkle() {
Expand All @@ -586,48 +522,6 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
return nil
}

func (s *StateDB) getStatelessDeletedStateObject(addr common.Address) *stateObject {
// Check that it is present in the witness, if running
// in stateless execution mode.
chunk := trieUtils.GetTreeKeyNonce(addr[:])
nb, ok := s.stateless[common.BytesToHash(chunk)]
if !ok {
log.Error("Failed to decode state object", "addr", addr)
s.setError(fmt.Errorf("could not find nonce chunk in proof: %x", chunk))
// TODO(gballet) remove after debug, and check the issue is found
panic("inivalid chunk")
return nil
}
chunk = trieUtils.GetTreeKeyBalance(addr[:])
bb, ok := s.stateless[common.BytesToHash(chunk)]
if !ok {
log.Error("Failed to decode state object", "addr", addr)
s.setError(fmt.Errorf("could not find balance chunk in proof: %x", chunk))
// TODO(gballet) remove after debug, and check the issue is found
panic("inivalid chunk")
return nil
}
chunk = trieUtils.GetTreeKeyCodeKeccak(addr[:])
cb, ok := s.stateless[common.BytesToHash(chunk)]
if !ok {
// Assume that this is an externally-owned account, and that
// the code has not been accessed.
// TODO(gballet) write this down, just like deletions, so
// that an error can be triggered if trying to access the
// account code.
copy(cb[:], emptyCodeHash)
}
data := &types.StateAccount{
Nonce: binary.BigEndian.Uint64(nb[:8]),
Balance: big.NewInt(0).SetBytes(bb[:]),
CodeHash: cb[:],
}
// Insert into the live set
obj := newObject(s, addr, *data)
s.setStateObject(obj)
return obj
}

// getDeletedStateObject is similar to getStateObject, but instead of returning
// nil for a deleted state object, it returns the actual object with the deleted
// flag set. This is needed by the state journal to revert to the correct s-
Expand All @@ -642,10 +536,6 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
data *types.StateAccount
err error
)
// if executing statelessly, bypass the snapshot and the db.
if s.stateless != nil {
return s.getStatelessDeletedStateObject(addr)
}
if s.snap != nil {
if metrics.EnabledExpensive {
defer func(start time.Time) { s.SnapshotAccountReads += time.Since(start) }(time.Now())
Expand Down Expand Up @@ -852,13 +742,6 @@ func (s *StateDB) Copy() *StateDB {
// to not blow up if we ever decide copy it in the middle of a transaction
state.accessList = s.accessList.Copy()

if s.stateless != nil {
state.stateless = make(map[common.Hash]common.Hash, len(s.stateless))
for addr, value := range s.stateless {
state.stateless[addr] = value
}
}

// If there's a prefetcher running, make an inactive copy of it that can
// only access data but does not actively preload (since the user will not
// know that they need to explicitly terminate an active copy).
Expand Down
37 changes: 0 additions & 37 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,43 +94,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
return receipts, allLogs, accesses, *usedGas, nil
}

func (p *StateProcessor) ProcessStateless(block *types.Block, statedb *state.StateDB, cfg vm.Config, leaves map[common.Hash]common.Hash) (types.Receipts, []*types.Log, uint64, error) {
var (
receipts types.Receipts
usedGas = new(uint64)
header = block.Header()
blockHash = block.Hash()
blockNumber = block.Number()
allLogs []*types.Log
gp = new(GasPool).AddGas(block.GasLimit())
)
// Mutate the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
}
blockContext := NewEVMBlockContext(header, p.bc, nil)
blockContext.StatelessAccesses = leaves
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
statedb.Prepare(tx.Hash(), i)
receipt, _, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
}
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), nil)

return receipts, allLogs, *usedGas, nil
}

func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, *types.AccessWitness, error) {
// Create a new context to be used in the EVM environment.
txContext := NewEVMTxContext(msg)
Expand Down
3 changes: 0 additions & 3 deletions core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package core

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
Expand Down Expand Up @@ -49,6 +48,4 @@ type Processor interface {
// the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles.
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *types.AccessWitness, uint64, error)

ProcessStateless(block *types.Block, statedb *state.StateDB, cfg vm.Config, accesses map[common.Hash]common.Hash) (types.Receipts, []*types.Log, uint64, error)
}

0 comments on commit f6f8616

Please sign in to comment.