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 }