github.com/ethereum/go-ethereum@v1.16.1/trie/verkle.go (about)

     1  // Copyright 2023 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 trie
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/ethdb"
    28  	"github.com/ethereum/go-ethereum/trie/trienode"
    29  	"github.com/ethereum/go-ethereum/trie/utils"
    30  	"github.com/ethereum/go-ethereum/triedb/database"
    31  	"github.com/ethereum/go-verkle"
    32  	"github.com/holiman/uint256"
    33  )
    34  
    35  var (
    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.NodeDatabase, 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  func (t *VerkleTrie) FlatdbNodeResolver(path []byte) ([]byte, error) {
    73  	return t.reader.node(path, common.Hash{})
    74  }
    75  
    76  // GetKey returns the sha3 preimage of a hashed key that was previously used
    77  // to store a value.
    78  func (t *VerkleTrie) GetKey(key []byte) []byte {
    79  	return key
    80  }
    81  
    82  // GetAccount implements state.Trie, retrieving the account with the specified
    83  // account address. If the specified account is not in the verkle tree, nil will
    84  // be returned. If the tree is corrupted, an error will be returned.
    85  func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error) {
    86  	var (
    87  		acc    = &types.StateAccount{}
    88  		values [][]byte
    89  		err    error
    90  	)
    91  	switch n := t.root.(type) {
    92  	case *verkle.InternalNode:
    93  		values, err = n.GetValuesAtStem(t.cache.GetStem(addr[:]), t.nodeResolver)
    94  		if err != nil {
    95  			return nil, fmt.Errorf("GetAccount (%x) error: %v", addr, err)
    96  		}
    97  	default:
    98  		return nil, errInvalidRootType
    99  	}
   100  	if values == nil {
   101  		return nil, nil
   102  	}
   103  	basicData := values[utils.BasicDataLeafKey]
   104  	acc.Nonce = binary.BigEndian.Uint64(basicData[utils.BasicDataNonceOffset:])
   105  	acc.Balance = new(uint256.Int).SetBytes(basicData[utils.BasicDataBalanceOffset : utils.BasicDataBalanceOffset+16])
   106  	acc.CodeHash = values[utils.CodeHashLeafKey]
   107  
   108  	// TODO account.Root is leave as empty. How should we handle the legacy account?
   109  	return acc, nil
   110  }
   111  
   112  // GetStorage implements state.Trie, retrieving the storage slot with the specified
   113  // account address and storage key. If the specified slot is not in the verkle tree,
   114  // nil will be returned. If the tree is corrupted, an error will be returned.
   115  func (t *VerkleTrie) GetStorage(addr common.Address, key []byte) ([]byte, error) {
   116  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
   117  	val, err := t.root.Get(k, t.nodeResolver)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return common.TrimLeftZeroes(val), nil
   122  }
   123  
   124  // UpdateAccount implements state.Trie, writing the provided account into the tree.
   125  // If the tree is corrupted, an error will be returned.
   126  func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount, codeLen int) error {
   127  	var (
   128  		err       error
   129  		basicData [32]byte
   130  		values    = make([][]byte, verkle.NodeWidth)
   131  		stem      = t.cache.GetStem(addr[:])
   132  	)
   133  
   134  	// Code size is encoded in BasicData as a 3-byte big-endian integer. Spare bytes are present
   135  	// before the code size to support bigger integers in the future. PutUint32(...) requires
   136  	// 4 bytes, so we need to shift the offset 1 byte to the left.
   137  	binary.BigEndian.PutUint32(basicData[utils.BasicDataCodeSizeOffset-1:], uint32(codeLen))
   138  	binary.BigEndian.PutUint64(basicData[utils.BasicDataNonceOffset:], acc.Nonce)
   139  	if acc.Balance.ByteLen() > 16 {
   140  		panic("balance too large")
   141  	}
   142  	acc.Balance.WriteToSlice(basicData[utils.BasicDataBalanceOffset : utils.BasicDataBalanceOffset+16])
   143  	values[utils.BasicDataLeafKey] = basicData[:]
   144  	values[utils.CodeHashLeafKey] = acc.CodeHash[:]
   145  
   146  	switch root := t.root.(type) {
   147  	case *verkle.InternalNode:
   148  		err = root.InsertValuesAtStem(stem, values, t.nodeResolver)
   149  	default:
   150  		return errInvalidRootType
   151  	}
   152  	if err != nil {
   153  		return fmt.Errorf("UpdateAccount (%x) error: %v", addr, err)
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  // UpdateStorage implements state.Trie, writing the provided storage slot into
   160  // the tree. If the tree is corrupted, an error will be returned.
   161  func (t *VerkleTrie) UpdateStorage(address common.Address, key, value []byte) error {
   162  	// Left padding the slot value to 32 bytes.
   163  	var v [32]byte
   164  	if len(value) >= 32 {
   165  		copy(v[:], value[:32])
   166  	} else {
   167  		copy(v[32-len(value):], value[:])
   168  	}
   169  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(address.Bytes()), key)
   170  	return t.root.Insert(k, v[:], t.nodeResolver)
   171  }
   172  
   173  // DeleteAccount leaves the account untouched, as no account deletion can happen
   174  // in verkle.
   175  // There is a special corner case, in which an account that is prefunded, CREATE2-d
   176  // and then SELFDESTRUCT-d should see its funds drained. EIP161 says that account
   177  // should be removed, but this is verboten by the verkle spec. This contains a
   178  // workaround in which the method checks for this corner case, and if so, overwrites
   179  // the balance with 0. This will be removed once the spec has been clarified.
   180  func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
   181  	k := utils.BasicDataKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()))
   182  	values, err := t.root.(*verkle.InternalNode).GetValuesAtStem(k, t.nodeResolver)
   183  	if err != nil {
   184  		return fmt.Errorf("Error getting data at %x in delete: %w", k, err)
   185  	}
   186  	var prefunded bool
   187  	for i, v := range values {
   188  		switch i {
   189  		case 0:
   190  			prefunded = len(v) == 32
   191  		case 1:
   192  			prefunded = len(v) == 32 && bytes.Equal(v, types.EmptyCodeHash[:])
   193  		default:
   194  			prefunded = v == nil
   195  		}
   196  		if !prefunded {
   197  			break
   198  		}
   199  	}
   200  	if prefunded {
   201  		t.root.Insert(k, common.Hash{}.Bytes(), t.nodeResolver)
   202  	}
   203  	return nil
   204  }
   205  
   206  // RollBackAccount removes the account info + code from the tree, unlike DeleteAccount
   207  // that will overwrite it with 0s. The first 64 storage slots are also removed.
   208  func (t *VerkleTrie) RollBackAccount(addr common.Address) error {
   209  	var (
   210  		evaluatedAddr = t.cache.Get(addr.Bytes())
   211  		basicDataKey  = utils.BasicDataKeyWithEvaluatedAddress(evaluatedAddr)
   212  	)
   213  	basicDataBytes, err := t.root.Get(basicDataKey, t.nodeResolver)
   214  	if err != nil {
   215  		return fmt.Errorf("rollback: error finding code size: %w", err)
   216  	}
   217  	if len(basicDataBytes) == 0 {
   218  		return errors.New("rollback: basic data is not existent")
   219  	}
   220  	// The code size is encoded in BasicData as a 3-byte big-endian integer. Spare bytes are present
   221  	// before the code size to support bigger integers in the future.
   222  	// LittleEndian.Uint32(...) expects 4-bytes, so we need to shift the offset 1-byte to the left.
   223  	codeSize := binary.BigEndian.Uint32(basicDataBytes[utils.BasicDataCodeSizeOffset-1:])
   224  
   225  	// Delete the account header + first 64 slots + first 128 code chunks
   226  	_, err = t.root.(*verkle.InternalNode).DeleteAtStem(basicDataKey[:31], t.nodeResolver)
   227  	if err != nil {
   228  		return fmt.Errorf("error rolling back account header: %w", err)
   229  	}
   230  
   231  	// Delete all further code
   232  	for i, chunknr := uint64(31*128), uint64(128); i < uint64(codeSize); i, chunknr = i+31*256, chunknr+256 {
   233  		// evaluate group key at the start of a new group
   234  		offset := uint256.NewInt(chunknr)
   235  		key := utils.CodeChunkKeyWithEvaluatedAddress(evaluatedAddr, offset)
   236  
   237  		if _, err = t.root.(*verkle.InternalNode).DeleteAtStem(key[:], t.nodeResolver); err != nil {
   238  			return fmt.Errorf("error deleting code chunk stem (addr=%x, offset=%d) error: %w", addr[:], offset, err)
   239  		}
   240  	}
   241  	return nil
   242  }
   243  
   244  // DeleteStorage implements state.Trie, deleting the specified storage slot from
   245  // the trie. If the storage slot was not existent in the trie, no error will be
   246  // returned. If the trie is corrupted, an error will be returned.
   247  func (t *VerkleTrie) DeleteStorage(addr common.Address, key []byte) error {
   248  	var zero [32]byte
   249  	k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
   250  	return t.root.Insert(k, zero[:], t.nodeResolver)
   251  }
   252  
   253  // Hash returns the root hash of the tree. It does not write to the database and
   254  // can be used even if the tree doesn't have one.
   255  func (t *VerkleTrie) Hash() common.Hash {
   256  	return t.root.Commit().Bytes()
   257  }
   258  
   259  // Commit writes all nodes to the tree's memory database.
   260  func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) {
   261  	root := t.root.(*verkle.InternalNode)
   262  	nodes, err := root.BatchSerialize()
   263  	if err != nil {
   264  		// Error return from this function indicates error in the code logic
   265  		// of BatchSerialize, and we fail catastrophically if this is the case.
   266  		panic(fmt.Errorf("BatchSerialize failed: %v", err))
   267  	}
   268  	nodeset := trienode.NewNodeSet(common.Hash{})
   269  	for _, node := range nodes {
   270  		// Hash parameter is not used in pathdb
   271  		nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
   272  	}
   273  	// Serialize root commitment form
   274  	return t.Hash(), nodeset
   275  }
   276  
   277  // NodeIterator implements state.Trie, returning an iterator that returns
   278  // nodes of the trie. Iteration starts at the key after the given start key.
   279  //
   280  // TODO(gballet, rjl493456442) implement it.
   281  func (t *VerkleTrie) NodeIterator(startKey []byte) (NodeIterator, error) {
   282  	panic("not implemented")
   283  }
   284  
   285  // Prove implements state.Trie, constructing a Merkle proof for key. The result
   286  // contains all encoded nodes on the path to the value at key. The value itself
   287  // is also included in the last node and can be retrieved by verifying the proof.
   288  //
   289  // If the trie does not contain a value for key, the returned proof contains all
   290  // nodes of the longest existing prefix of the key (at least the root), ending
   291  // with the node that proves the absence of the key.
   292  //
   293  // TODO(gballet, rjl493456442) implement it.
   294  func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
   295  	panic("not implemented")
   296  }
   297  
   298  // Copy returns a deep-copied verkle tree.
   299  func (t *VerkleTrie) Copy() *VerkleTrie {
   300  	return &VerkleTrie{
   301  		root:   t.root.Copy(),
   302  		cache:  t.cache,
   303  		reader: t.reader,
   304  	}
   305  }
   306  
   307  // IsVerkle indicates if the trie is a Verkle trie.
   308  func (t *VerkleTrie) IsVerkle() bool {
   309  	return true
   310  }
   311  
   312  // Proof builds and returns the verkle multiproof for keys, built against
   313  // the pre tree. The post tree is passed in order to add the post values
   314  // to that proof.
   315  func (t *VerkleTrie) Proof(posttrie *VerkleTrie, keys [][]byte) (*verkle.VerkleProof, verkle.StateDiff, error) {
   316  	var postroot verkle.VerkleNode
   317  	if posttrie != nil {
   318  		postroot = posttrie.root
   319  	}
   320  	proof, _, _, _, err := verkle.MakeVerkleMultiProof(t.root, postroot, keys, t.FlatdbNodeResolver)
   321  	if err != nil {
   322  		return nil, nil, err
   323  	}
   324  	p, kvps, err := verkle.SerializeProof(proof)
   325  	if err != nil {
   326  		return nil, nil, err
   327  	}
   328  	return p, kvps, nil
   329  }
   330  
   331  // ChunkedCode represents a sequence of 32-bytes chunks of code (31 bytes of which
   332  // are actual code, and 1 byte is the pushdata offset).
   333  type ChunkedCode []byte
   334  
   335  // Copy the values here so as to avoid an import cycle
   336  const (
   337  	PUSH1  = byte(0x60)
   338  	PUSH32 = byte(0x7f)
   339  )
   340  
   341  // ChunkifyCode generates the chunked version of an array representing EVM bytecode
   342  func ChunkifyCode(code []byte) ChunkedCode {
   343  	var (
   344  		chunkOffset = 0 // offset in the chunk
   345  		chunkCount  = len(code) / 31
   346  		codeOffset  = 0 // offset in the code
   347  	)
   348  	if len(code)%31 != 0 {
   349  		chunkCount++
   350  	}
   351  	chunks := make([]byte, chunkCount*32)
   352  	for i := 0; i < chunkCount; i++ {
   353  		// number of bytes to copy, 31 unless the end of the code has been reached.
   354  		end := 31 * (i + 1)
   355  		if len(code) < end {
   356  			end = len(code)
   357  		}
   358  		copy(chunks[i*32+1:], code[31*i:end]) // copy the code itself
   359  
   360  		// chunk offset = taken from the last chunk.
   361  		if chunkOffset > 31 {
   362  			// skip offset calculation if push data covers the whole chunk
   363  			chunks[i*32] = 31
   364  			chunkOffset = 1
   365  			continue
   366  		}
   367  		chunks[32*i] = byte(chunkOffset)
   368  		chunkOffset = 0
   369  
   370  		// Check each instruction and update the offset it should be 0 unless
   371  		// a PUSH-N overflows.
   372  		for ; codeOffset < end; codeOffset++ {
   373  			if code[codeOffset] >= PUSH1 && code[codeOffset] <= PUSH32 {
   374  				codeOffset += int(code[codeOffset] - PUSH1 + 1)
   375  				if codeOffset+1 >= 31*(i+1) {
   376  					codeOffset++
   377  					chunkOffset = codeOffset - 31*(i+1)
   378  					break
   379  				}
   380  			}
   381  		}
   382  	}
   383  	return chunks
   384  }
   385  
   386  // UpdateContractCode implements state.Trie, writing the provided contract code
   387  // into the trie.
   388  // Note that the code-size *must* be already saved by a previous UpdateAccount call.
   389  func (t *VerkleTrie) UpdateContractCode(addr common.Address, codeHash common.Hash, code []byte) error {
   390  	var (
   391  		chunks = ChunkifyCode(code)
   392  		values [][]byte
   393  		key    []byte
   394  		err    error
   395  	)
   396  	for i, chunknr := 0, uint64(0); i < len(chunks); i, chunknr = i+32, chunknr+1 {
   397  		groupOffset := (chunknr + 128) % 256
   398  		if groupOffset == 0 /* start of new group */ || chunknr == 0 /* first chunk in header group */ {
   399  			values = make([][]byte, verkle.NodeWidth)
   400  			key = utils.CodeChunkKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), uint256.NewInt(chunknr))
   401  		}
   402  		values[groupOffset] = chunks[i : i+32]
   403  
   404  		if groupOffset == 255 || len(chunks)-i <= 32 {
   405  			switch root := t.root.(type) {
   406  			case *verkle.InternalNode:
   407  				err = root.InsertValuesAtStem(key[:31], values, t.nodeResolver)
   408  				if err != nil {
   409  					return fmt.Errorf("UpdateContractCode (addr=%x) error: %w", addr[:], err)
   410  				}
   411  			default:
   412  				return errInvalidRootType
   413  			}
   414  		}
   415  	}
   416  	return nil
   417  }
   418  
   419  func (t *VerkleTrie) ToDot() string {
   420  	return verkle.ToDot(t.root)
   421  }
   422  
   423  func (t *VerkleTrie) nodeResolver(path []byte) ([]byte, error) {
   424  	return t.reader.node(path, common.Hash{})
   425  }
   426  
   427  // Witness returns a set containing all trie nodes that have been accessed.
   428  func (t *VerkleTrie) Witness() map[string]struct{} {
   429  	panic("not implemented")
   430  }