github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/trie/verkle.go (about)

     1  // Copyright 2023 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 trie
    18  
    19  import (
    20  	"encoding/binary"
    21  	"errors"
    22  	"fmt"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/ethdb"
    27  	"github.com/ethereum/go-ethereum/trie/trienode"
    28  	"github.com/ethereum/go-ethereum/trie/utils"
    29  	"github.com/ethereum/go-ethereum/triedb/database"
    30  	"github.com/gballet/go-verkle"
    31  	"github.com/holiman/uint256"
    32  )
    33  
    34  var (
    35  	zero               [32]byte
    36  	errInvalidRootType = errors.New("invalid node type for root")
    37  )
    38  
    39  // VerkleTrie is a wrapper around VerkleNode that implements the trie.Trie
    40  // interface so that Verkle trees can be reused verbatim.
    41  type VerkleTrie struct {
    42  	root   verkle.VerkleNode
    43  	cache  *utils.PointCache
    44  	reader *trieReader
    45  }
    46  
    47  // NewVerkleTrie constructs a verkle tree based on the specified root hash.
    48  func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCache) (*VerkleTrie, error) {
    49  	reader, err := newTrieReader(root, common.Hash{}, db)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	// Parse the root verkle node if it's not empty.
    54  	node := verkle.New()
    55  	if root != types.EmptyVerkleHash && root != types.EmptyRootHash {
    56  		blob, err := reader.node(nil, common.Hash{})
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		node, err = verkle.ParseNode(blob, 0)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  	}
    65  	return &VerkleTrie{
    66  		root:   node,
    67  		cache:  cache,
    68  		reader: reader,
    69  	}, nil
    70  }
    71  
    72  // GetKey returns the sha3 preimage of a hashed key that was previously used
    73  // to store a value.
    74  func (t *VerkleTrie) GetKey(key []byte) []byte {
    75  	return key
    76  }
    77  
    78  // GetAccount implements state.Trie, retrieving the account with the specified
    79  // account address. If the specified account is not in the verkle tree, nil will
    80  // be returned. If the tree is corrupted, an error will be returned.
    81  func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error) {
    82  	var (
    83  		acc    = &types.StateAccount{}
    84  		values [][]byte
    85  		err    error
    86  	)
    87  	switch n := t.root.(type) {
    88  	case *verkle.InternalNode:
    89  		values, err = n.GetValuesAtStem(t.cache.GetStem(addr[:]), t.nodeResolver)
    90  		if err != nil {
    91  			return nil, fmt.Errorf("GetAccount (%x) error: %v", addr, err)
    92  		}
    93  	default:
    94  		return nil, errInvalidRootType
    95  	}
    96  	if values == nil {
    97  		return nil, nil
    98  	}
    99  	// Decode nonce in little-endian
   100  	if len(values[utils.NonceLeafKey]) > 0 {
   101  		acc.Nonce = binary.LittleEndian.Uint64(values[utils.NonceLeafKey])
   102  	}
   103  	// Decode balance in little-endian
   104  	var balance [32]byte
   105  	copy(balance[:], values[utils.BalanceLeafKey])
   106  	for i := 0; i < len(balance)/2; i++ {
   107  		balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1]
   108  	}
   109  	acc.Balance = new(uint256.Int).SetBytes32(balance[:])
   110  
   111  	// Decode codehash
   112  	acc.CodeHash = values[utils.CodeKeccakLeafKey]
   113  
   114  	// TODO account.Root is leave as empty. How should we handle the legacy account?
   115  	return acc, nil
   116  }
   117  
   118  // GetStorage implements state.Trie, retrieving the storage slot with the specified
   119  // account address and storage key. If the specified slot is not in the verkle tree,
   120  // nil will be returned. If the tree is corrupted, an error will be returned.
   121  func (t *VerkleTrie) GetStorage(addr common.Address, key []byte) ([]byte, error) {
   122  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
   123  	val, err := t.root.Get(k, t.nodeResolver)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	return common.TrimLeftZeroes(val), nil
   128  }
   129  
   130  // UpdateAccount implements state.Trie, writing the provided account into the tree.
   131  // If the tree is corrupted, an error will be returned.
   132  func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) error {
   133  	var (
   134  		err            error
   135  		nonce, balance [32]byte
   136  		values         = make([][]byte, verkle.NodeWidth)
   137  	)
   138  	values[utils.VersionLeafKey] = zero[:]
   139  	values[utils.CodeKeccakLeafKey] = acc.CodeHash[:]
   140  
   141  	// Encode nonce in little-endian
   142  	binary.LittleEndian.PutUint64(nonce[:], acc.Nonce)
   143  	values[utils.NonceLeafKey] = nonce[:]
   144  
   145  	// Encode balance in little-endian
   146  	bytes := acc.Balance.Bytes()
   147  	if len(bytes) > 0 {
   148  		for i, b := range bytes {
   149  			balance[len(bytes)-i-1] = b
   150  		}
   151  	}
   152  	values[utils.BalanceLeafKey] = balance[:]
   153  
   154  	switch n := t.root.(type) {
   155  	case *verkle.InternalNode:
   156  		err = n.InsertValuesAtStem(t.cache.GetStem(addr[:]), values, t.nodeResolver)
   157  		if err != nil {
   158  			return fmt.Errorf("UpdateAccount (%x) error: %v", addr, err)
   159  		}
   160  	default:
   161  		return errInvalidRootType
   162  	}
   163  	// TODO figure out if the code size needs to be updated, too
   164  	return nil
   165  }
   166  
   167  // UpdateStorage implements state.Trie, writing the provided storage slot into
   168  // the tree. If the tree is corrupted, an error will be returned.
   169  func (t *VerkleTrie) UpdateStorage(address common.Address, key, value []byte) error {
   170  	// Left padding the slot value to 32 bytes.
   171  	var v [32]byte
   172  	if len(value) >= 32 {
   173  		copy(v[:], value[:32])
   174  	} else {
   175  		copy(v[32-len(value):], value[:])
   176  	}
   177  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(address.Bytes()), key)
   178  	return t.root.Insert(k, v[:], t.nodeResolver)
   179  }
   180  
   181  // DeleteAccount implements state.Trie, deleting the specified account from the
   182  // trie. If the account was not existent in the trie, no error will be returned.
   183  // If the trie is corrupted, an error will be returned.
   184  func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
   185  	var (
   186  		err    error
   187  		values = make([][]byte, verkle.NodeWidth)
   188  	)
   189  	for i := 0; i < verkle.NodeWidth; i++ {
   190  		values[i] = zero[:]
   191  	}
   192  	switch n := t.root.(type) {
   193  	case *verkle.InternalNode:
   194  		err = n.InsertValuesAtStem(t.cache.GetStem(addr.Bytes()), values, t.nodeResolver)
   195  		if err != nil {
   196  			return fmt.Errorf("DeleteAccount (%x) error: %v", addr, err)
   197  		}
   198  	default:
   199  		return errInvalidRootType
   200  	}
   201  	return nil
   202  }
   203  
   204  // DeleteStorage implements state.Trie, deleting the specified storage slot from
   205  // the trie. If the storage slot was not existent in the trie, no error will be
   206  // returned. If the trie is corrupted, an error will be returned.
   207  func (t *VerkleTrie) DeleteStorage(addr common.Address, key []byte) error {
   208  	var zero [32]byte
   209  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
   210  	return t.root.Insert(k, zero[:], t.nodeResolver)
   211  }
   212  
   213  // Hash returns the root hash of the tree. It does not write to the database and
   214  // can be used even if the tree doesn't have one.
   215  func (t *VerkleTrie) Hash() common.Hash {
   216  	return t.root.Commit().Bytes()
   217  }
   218  
   219  // Commit writes all nodes to the tree's memory database.
   220  func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
   221  	root, ok := t.root.(*verkle.InternalNode)
   222  	if !ok {
   223  		return common.Hash{}, nil, errors.New("unexpected root node type")
   224  	}
   225  	nodes, err := root.BatchSerialize()
   226  	if err != nil {
   227  		return common.Hash{}, nil, fmt.Errorf("serializing tree nodes: %s", err)
   228  	}
   229  	nodeset := trienode.NewNodeSet(common.Hash{})
   230  	for _, node := range nodes {
   231  		// hash parameter is not used in pathdb
   232  		nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
   233  	}
   234  	// Serialize root commitment form
   235  	return t.Hash(), nodeset, nil
   236  }
   237  
   238  // NodeIterator implements state.Trie, returning an iterator that returns
   239  // nodes of the trie. Iteration starts at the key after the given start key.
   240  //
   241  // TODO(gballet, rjl493456442) implement it.
   242  func (t *VerkleTrie) NodeIterator(startKey []byte) (NodeIterator, error) {
   243  	panic("not implemented")
   244  }
   245  
   246  // Prove implements state.Trie, constructing a Merkle proof for key. The result
   247  // contains all encoded nodes on the path to the value at key. The value itself
   248  // is also included in the last node and can be retrieved by verifying the proof.
   249  //
   250  // If the trie does not contain a value for key, the returned proof contains all
   251  // nodes of the longest existing prefix of the key (at least the root), ending
   252  // with the node that proves the absence of the key.
   253  //
   254  // TODO(gballet, rjl493456442) implement it.
   255  func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
   256  	panic("not implemented")
   257  }
   258  
   259  // Copy returns a deep-copied verkle tree.
   260  func (t *VerkleTrie) Copy() *VerkleTrie {
   261  	return &VerkleTrie{
   262  		root:   t.root.Copy(),
   263  		cache:  t.cache,
   264  		reader: t.reader,
   265  	}
   266  }
   267  
   268  // IsVerkle indicates if the trie is a Verkle trie.
   269  func (t *VerkleTrie) IsVerkle() bool {
   270  	return true
   271  }
   272  
   273  // ChunkedCode represents a sequence of 32-bytes chunks of code (31 bytes of which
   274  // are actual code, and 1 byte is the pushdata offset).
   275  type ChunkedCode []byte
   276  
   277  // Copy the values here so as to avoid an import cycle
   278  const (
   279  	PUSH1  = byte(0x60)
   280  	PUSH32 = byte(0x7f)
   281  )
   282  
   283  // ChunkifyCode generates the chunked version of an array representing EVM bytecode
   284  func ChunkifyCode(code []byte) ChunkedCode {
   285  	var (
   286  		chunkOffset = 0 // offset in the chunk
   287  		chunkCount  = len(code) / 31
   288  		codeOffset  = 0 // offset in the code
   289  	)
   290  	if len(code)%31 != 0 {
   291  		chunkCount++
   292  	}
   293  	chunks := make([]byte, chunkCount*32)
   294  	for i := 0; i < chunkCount; i++ {
   295  		// number of bytes to copy, 31 unless the end of the code has been reached.
   296  		end := 31 * (i + 1)
   297  		if len(code) < end {
   298  			end = len(code)
   299  		}
   300  		copy(chunks[i*32+1:], code[31*i:end]) // copy the code itself
   301  
   302  		// chunk offset = taken from the last chunk.
   303  		if chunkOffset > 31 {
   304  			// skip offset calculation if push data covers the whole chunk
   305  			chunks[i*32] = 31
   306  			chunkOffset = 1
   307  			continue
   308  		}
   309  		chunks[32*i] = byte(chunkOffset)
   310  		chunkOffset = 0
   311  
   312  		// Check each instruction and update the offset it should be 0 unless
   313  		// a PUSH-N overflows.
   314  		for ; codeOffset < end; codeOffset++ {
   315  			if code[codeOffset] >= PUSH1 && code[codeOffset] <= PUSH32 {
   316  				codeOffset += int(code[codeOffset] - PUSH1 + 1)
   317  				if codeOffset+1 >= 31*(i+1) {
   318  					codeOffset++
   319  					chunkOffset = codeOffset - 31*(i+1)
   320  					break
   321  				}
   322  			}
   323  		}
   324  	}
   325  	return chunks
   326  }
   327  
   328  // UpdateContractCode implements state.Trie, writing the provided contract code
   329  // into the trie.
   330  func (t *VerkleTrie) UpdateContractCode(addr common.Address, codeHash common.Hash, code []byte) error {
   331  	var (
   332  		chunks = ChunkifyCode(code)
   333  		values [][]byte
   334  		key    []byte
   335  		err    error
   336  	)
   337  	for i, chunknr := 0, uint64(0); i < len(chunks); i, chunknr = i+32, chunknr+1 {
   338  		groupOffset := (chunknr + 128) % 256
   339  		if groupOffset == 0 /* start of new group */ || chunknr == 0 /* first chunk in header group */ {
   340  			values = make([][]byte, verkle.NodeWidth)
   341  			key = utils.CodeChunkKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), uint256.NewInt(chunknr))
   342  		}
   343  		values[groupOffset] = chunks[i : i+32]
   344  
   345  		// Reuse the calculated key to also update the code size.
   346  		if i == 0 {
   347  			cs := make([]byte, 32)
   348  			binary.LittleEndian.PutUint64(cs, uint64(len(code)))
   349  			values[utils.CodeSizeLeafKey] = cs
   350  		}
   351  		if groupOffset == 255 || len(chunks)-i <= 32 {
   352  			switch root := t.root.(type) {
   353  			case *verkle.InternalNode:
   354  				err = root.InsertValuesAtStem(key[:31], values, t.nodeResolver)
   355  				if err != nil {
   356  					return fmt.Errorf("UpdateContractCode (addr=%x) error: %w", addr[:], err)
   357  				}
   358  			default:
   359  				return errInvalidRootType
   360  			}
   361  		}
   362  	}
   363  	return nil
   364  }
   365  
   366  func (t *VerkleTrie) ToDot() string {
   367  	return verkle.ToDot(t.root)
   368  }
   369  
   370  func (t *VerkleTrie) nodeResolver(path []byte) ([]byte, error) {
   371  	return t.reader.node(path, common.Hash{})
   372  }