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 }