github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/trie.go (about) 1 package ledger 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "encoding/json" 7 "errors" 8 "fmt" 9 10 "github.com/fxamacker/cbor/v2" 11 12 cryptoHash "github.com/onflow/crypto/hash" 13 14 "github.com/onflow/flow-go/ledger/common/bitutils" 15 "github.com/onflow/flow-go/ledger/common/hash" 16 "github.com/onflow/flow-go/model/flow" 17 ) 18 19 // Path captures storage path of a payload; 20 // where we store a payload in the ledger 21 type Path hash.Hash 22 23 func (p Path) MarshalJSON() ([]byte, error) { 24 return json.Marshal(hex.EncodeToString(p[:])) 25 } 26 27 // DummyPath is an arbitrary path value, used in function error returns. 28 var DummyPath = Path(hash.DummyHash) 29 30 // PathLen is the size of paths in bytes. 31 const PathLen = 32 32 33 // The node maximum height or the tree height. 34 // It corresponds to the path size in bits. 35 const NodeMaxHeight = PathLen * 8 36 37 // we are currently supporting paths of a size equal to 32 bytes. 38 // I.e. path length from the rootNode of a fully expanded tree to the leaf node is 256. 39 // A path of length k is comprised of k+1 vertices. Hence, we need 257 default hashes. 40 const defaultHashesNum = NodeMaxHeight + 1 41 42 // array to store all default hashes 43 var defaultHashes [defaultHashesNum]hash.Hash 44 45 func init() { 46 47 // default value and default hash value for a default node 48 var defaultLeafHash hash.Hash 49 castedPointer := (*[hash.HashLen]byte)(&defaultLeafHash) 50 cryptoHash.ComputeSHA3_256(castedPointer, []byte("default:")) 51 52 // Creates the Default hashes from base to level height 53 defaultHashes[0] = defaultLeafHash 54 for i := 1; i < defaultHashesNum; i++ { 55 defaultHashes[i] = hash.HashInterNode(defaultHashes[i-1], defaultHashes[i-1]) 56 } 57 } 58 59 // GetDefaultHashForHeight returns the default hashes of the SMT at a specified height. 60 // 61 // For each tree level N, there is a default hash equal to the chained 62 // hashing of the default value N times. 63 func GetDefaultHashForHeight(height int) hash.Hash { 64 return defaultHashes[height] 65 } 66 67 // ComputeCompactValue computes the value for the node considering the sub tree 68 // to only include this value and default values. It writes the hash result to the result input. 69 // UNCHECKED: payload!= nil 70 func ComputeCompactValue(path hash.Hash, value []byte, nodeHeight int) hash.Hash { 71 // if register is unallocated: return default hash 72 if len(value) == 0 { 73 return GetDefaultHashForHeight(nodeHeight) 74 } 75 76 var out hash.Hash 77 out = hash.HashLeaf(path, value) // we first compute the hash of the fully-expanded leaf 78 for h := 1; h <= nodeHeight; h++ { // then, we hash our way upwards towards the root until we hit the specified nodeHeight 79 // h is the height of the node, whose hash we are computing in this iteration. 80 // The hash is computed from the node's children at height h-1. 81 bit := bitutils.ReadBit(path[:], NodeMaxHeight-h) 82 if bit == 1 { // right branching 83 out = hash.HashInterNode(GetDefaultHashForHeight(h-1), out) 84 } else { // left branching 85 out = hash.HashInterNode(out, GetDefaultHashForHeight(h-1)) 86 } 87 } 88 return out 89 } 90 91 // TrieRead captures a trie read query 92 type TrieRead struct { 93 RootHash RootHash 94 Paths []Path 95 } 96 97 // TrieReadSinglePayload contains trie read query for a single payload 98 type TrieReadSingleValue struct { 99 RootHash RootHash 100 Path Path 101 } 102 103 // TrieUpdate holds all data for a trie update 104 type TrieUpdate struct { 105 RootHash RootHash 106 Paths []Path 107 Payloads []*Payload 108 } 109 110 // Size returns number of paths in the trie update 111 func (u *TrieUpdate) Size() int { 112 return len(u.Paths) 113 } 114 115 // IsEmpty returns true if key or value is not empty 116 func (u *TrieUpdate) IsEmpty() bool { 117 return u.Size() == 0 118 } 119 120 func (u *TrieUpdate) String() string { 121 str := "Trie Update:\n " 122 str += "\t triehash : " + u.RootHash.String() + "\n" 123 for i, p := range u.Paths { 124 str += fmt.Sprintf("\t\t path %d : %s\n", i, p) 125 } 126 str += fmt.Sprintf("\t paths len: %d , bytesize: %d\n", len(u.Paths), len(u.Paths)*PathLen) 127 tp := 0 128 for _, p := range u.Payloads { 129 tp += p.Size() 130 } 131 str += fmt.Sprintf("\t total size of payloads : %d \n", tp) 132 return str 133 } 134 135 // Equals compares this trie update to another trie update 136 func (u *TrieUpdate) Equals(other *TrieUpdate) bool { 137 if other == nil { 138 return false 139 } 140 if !u.RootHash.Equals(other.RootHash) { 141 return false 142 } 143 if len(u.Paths) != len(other.Paths) { 144 return false 145 } 146 for i := range u.Paths { 147 if !u.Paths[i].Equals(other.Paths[i]) { 148 return false 149 } 150 } 151 152 if len(u.Payloads) != len(other.Payloads) { 153 return false 154 } 155 for i := range u.Payloads { 156 if !u.Payloads[i].Equals(other.Payloads[i]) { 157 return false 158 } 159 } 160 return true 161 } 162 163 // RootHash captures the root hash of a trie 164 type RootHash hash.Hash 165 166 func (rh RootHash) MarshalJSON() ([]byte, error) { 167 return json.Marshal(rh.String()) 168 } 169 170 func (rh RootHash) String() string { 171 return hex.EncodeToString(rh[:]) 172 } 173 174 // Equals compares the root hash to another one 175 func (rh RootHash) Equals(o RootHash) bool { 176 return rh == o 177 } 178 179 // ToRootHash converts a byte slice into a root hash. 180 // It returns an error if the slice has an invalid length. 181 func ToRootHash(rootHashBytes []byte) (RootHash, error) { 182 var rootHash RootHash 183 if len(rootHashBytes) != len(rootHash) { 184 return RootHash(hash.DummyHash), fmt.Errorf("expecting %d bytes but got %d bytes", len(rootHash), len(rootHashBytes)) 185 } 186 copy(rootHash[:], rootHashBytes) 187 return rootHash, nil 188 } 189 190 func (p Path) String() string { 191 str := "" 192 for _, i := range p { 193 str += fmt.Sprintf("%08b", i) 194 } 195 str = str[0:8] + "..." + str[len(str)-8:] 196 return str 197 } 198 199 // Equals compares this path to another path 200 func (p Path) Equals(o Path) bool { 201 return p == o 202 } 203 204 // ToPath converts a byte slice into a path. 205 // It returns an error if the slice has an invalid length. 206 func ToPath(pathBytes []byte) (Path, error) { 207 var path Path 208 if len(pathBytes) != len(path) { 209 return DummyPath, fmt.Errorf("expecting %d bytes but got %d bytes", len(path), len(pathBytes)) 210 } 211 copy(path[:], pathBytes) 212 return path, nil 213 } 214 215 // encKey represents an encoded ledger key. 216 type encKey []byte 217 218 // Size returns the byte size of the encoded key. 219 func (k encKey) Size() int { 220 return len(k) 221 } 222 223 // String returns the string representation of the encoded key. 224 func (k encKey) String() string { 225 return hex.EncodeToString(k) 226 } 227 228 // Equals compares this encoded key to another encoded key. 229 // A nil encoded key is equivalent to an empty encoded key. 230 func (k encKey) Equals(other encKey) bool { 231 return bytes.Equal(k, other) 232 } 233 234 // DeepCopy returns a deep copy of the encoded key. 235 func (k encKey) DeepCopy() encKey { 236 newK := make([]byte, len(k)) 237 copy(newK, k) 238 return newK 239 } 240 241 const ( 242 KeyPartOwner = uint16(0) 243 // Deprecated: KeyPartController was only used by the very first 244 // version of Cadence for access control, which was later retired 245 _ = uint16(1) // DO NOT REUSE 246 KeyPartKey = uint16(2) 247 ) 248 249 // Payload is the smallest immutable storable unit in ledger 250 type Payload struct { 251 // encKey is key encoded using PayloadVersion. 252 // Version and type data are not encoded to save 3 bytes. 253 // NOTE: encKey translates to Key{} when encKey is 254 // one of these three values: 255 // nil, []byte{}, []byte{0,0}. 256 encKey encKey 257 value Value 258 } 259 260 // serializablePayload is used to serialize ledger.Payload. 261 // Encoder only serializes exported fields and ledger.Payload's 262 // key and value fields are not exported. So it is necessary to 263 // use serializablePayload for encoding. 264 type serializablePayload struct { 265 Key Key 266 Value Value 267 } 268 269 // MarshalJSON returns JSON encoding of p. 270 func (p Payload) MarshalJSON() ([]byte, error) { 271 k, err := p.Key() 272 if err != nil { 273 return nil, err 274 } 275 sp := serializablePayload{Key: k, Value: p.value} 276 return json.Marshal(sp) 277 } 278 279 // UnmarshalJSON unmarshals a JSON value of payload. 280 func (p *Payload) UnmarshalJSON(b []byte) error { 281 if p == nil { 282 return errors.New("UnmarshalJSON on nil Payload") 283 } 284 var sp serializablePayload 285 if err := json.Unmarshal(b, &sp); err != nil { 286 return err 287 } 288 p.encKey = encodeKey(&sp.Key, PayloadVersion) 289 p.value = sp.Value 290 return nil 291 } 292 293 // MarshalCBOR returns CBOR encoding of p. 294 func (p Payload) MarshalCBOR() ([]byte, error) { 295 k, err := p.Key() 296 if err != nil { 297 return nil, err 298 } 299 sp := serializablePayload{Key: k, Value: p.value} 300 return cbor.Marshal(sp) 301 } 302 303 // UnmarshalCBOR unmarshals a CBOR value of payload. 304 func (p *Payload) UnmarshalCBOR(b []byte) error { 305 if p == nil { 306 return errors.New("UnmarshalCBOR on nil payload") 307 } 308 var sp serializablePayload 309 if err := cbor.Unmarshal(b, &sp); err != nil { 310 return err 311 } 312 p.encKey = encodeKey(&sp.Key, PayloadVersion) 313 p.value = sp.Value 314 return nil 315 } 316 317 // Key returns payload key. 318 // Error indicates that ledger.Key can't be created from payload key, so 319 // migration and reporting (known callers) should abort. 320 // CAUTION: do not modify returned key because it shares underlying data with payload key. 321 func (p *Payload) Key() (Key, error) { 322 if p == nil || len(p.encKey) == 0 { 323 return Key{}, nil 324 } 325 k, err := decodeKey(p.encKey, true, PayloadVersion) 326 if err != nil { 327 return Key{}, err 328 } 329 return *k, nil 330 } 331 332 // EncodedKey returns payload key. 333 // CAUTION: do not modify returned encoded key 334 // because it shares underlying data with payload key. 335 func (p *Payload) EncodedKey() []byte { 336 if p == nil { 337 return nil 338 } 339 return p.encKey 340 } 341 342 // Address returns: 343 // - (address, nil) if the payload is for an account, the account address is returned 344 // - (flow.EmptyAddress, nil) if the payload is not for an account (global register) 345 // - (flow.EmptyAddress, err) if running into any exception 346 // The zero address is used for global Payloads and is not an actual account 347 func (p *Payload) Address() (flow.Address, error) { 348 if p == nil { 349 return flow.EmptyAddress, fmt.Errorf("failed to get payload address: payload is nil") 350 } 351 if len(p.encKey) == 0 { 352 return flow.EmptyAddress, fmt.Errorf("failed to get payload address: encoded key is empty") 353 } 354 b, found, err := decodeKeyPartValueByType(p.encKey, KeyPartOwner, true, PayloadVersion) 355 if err != nil { 356 return flow.EmptyAddress, err 357 } 358 if !found { 359 return flow.EmptyAddress, fmt.Errorf("failed to find address by type %d", KeyPartOwner) 360 } 361 return flow.BytesToAddress(b), nil 362 } 363 364 // Value returns payload value. 365 // CAUTION: do not modify returned value because it shares underlying data with payload value. 366 func (p *Payload) Value() Value { 367 if p == nil { 368 return Value{} 369 } 370 return p.value 371 } 372 373 // Size returns the size of the payload 374 func (p *Payload) Size() int { 375 if p == nil { 376 return 0 377 } 378 return p.encKey.Size() + p.value.Size() 379 } 380 381 // IsEmpty returns true if payload is nil or value is empty 382 func (p *Payload) IsEmpty() bool { 383 return p == nil || p.value.Size() == 0 384 } 385 386 // TODO fix me 387 func (p *Payload) String() string { 388 // TODO improve this key, values 389 return p.encKey.String() + " " + p.value.String() 390 } 391 392 // Equals compares this payload to another payload 393 // A nil payload is equivalent to an empty payload. 394 func (p *Payload) Equals(other *Payload) bool { 395 if p == nil || (p.encKey.Size() == 0 && p.value.Size() == 0) { 396 return other == nil || (other.encKey.Size() == 0 && other.value.Size() == 0) 397 } 398 if other == nil { 399 return false 400 } 401 return p.encKey.Equals(other.encKey) && p.value.Equals(other.value) 402 } 403 404 // ValueEquals compares this payload value to another payload value. 405 // A nil payload is equivalent to an empty payload. 406 // NOTE: prefer using this function over payload.Value.Equals() 407 // when comparing payload values. payload.ValueEquals() handles 408 // nil payload, while payload.Value.Equals() panics on nil payload. 409 func (p *Payload) ValueEquals(other *Payload) bool { 410 pEmpty := p.IsEmpty() 411 otherEmpty := other.IsEmpty() 412 if pEmpty != otherEmpty { 413 // Only one payload is empty 414 return false 415 } 416 if pEmpty { 417 // Both payloads are empty 418 return true 419 } 420 // Compare values since both payloads are not empty. 421 return p.value.Equals(other.value) 422 } 423 424 // DeepCopy returns a deep copy of the payload 425 func (p *Payload) DeepCopy() *Payload { 426 if p == nil { 427 return nil 428 } 429 k := p.encKey.DeepCopy() 430 v := p.value.DeepCopy() 431 return &Payload{encKey: k, value: v} 432 } 433 434 // NewPayload returns a new payload 435 func NewPayload(key Key, value Value) *Payload { 436 ek := encodeKey(&key, PayloadVersion) 437 return &Payload{encKey: ek, value: value} 438 } 439 440 // EmptyPayload returns an empty payload 441 func EmptyPayload() *Payload { 442 return &Payload{} 443 } 444 445 // TrieProof includes all the information needed to walk 446 // through a trie branch from an specific leaf node (key) 447 // up to the root of the trie. 448 type TrieProof struct { 449 Path Path // path 450 Payload *Payload // payload 451 Interims []hash.Hash // the non-default intermediate nodes in the proof 452 Inclusion bool // flag indicating if this is an inclusion or exclusion proof 453 Flags []byte // The flags of the proofs (is set if an intermediate node has a non-default) 454 Steps uint8 // number of steps for the proof (path len) // TODO: should this be a type allowing for larger values? 455 } 456 457 // NewTrieProof creates a new instance of Trie Proof 458 func NewTrieProof() *TrieProof { 459 return &TrieProof{ 460 Payload: EmptyPayload(), 461 Interims: make([]hash.Hash, 0), 462 Inclusion: false, 463 Flags: make([]byte, PathLen), 464 Steps: 0, 465 } 466 } 467 468 func (p *TrieProof) String() string { 469 flagStr := "" 470 for _, f := range p.Flags { 471 flagStr += fmt.Sprintf("%08b", f) 472 } 473 proofStr := fmt.Sprintf("size: %d flags: %v\n", p.Steps, flagStr) 474 proofStr += fmt.Sprintf("\t path: %v payload: %v\n", p.Path, p.Payload) 475 476 if p.Inclusion { 477 proofStr += "\t inclusion proof:\n" 478 } else { 479 proofStr += "\t noninclusion proof:\n" 480 } 481 interimIndex := 0 482 for j := 0; j < int(p.Steps); j++ { 483 // if bit is set 484 if p.Flags[j/8]&(1<<(7-j%8)) != 0 { 485 proofStr += fmt.Sprintf("\t\t %d: [%x]\n", j, p.Interims[interimIndex]) 486 interimIndex++ 487 } 488 } 489 return proofStr 490 } 491 492 // Equals compares this proof to another payload 493 func (p *TrieProof) Equals(o *TrieProof) bool { 494 if o == nil { 495 return false 496 } 497 if !p.Path.Equals(o.Path) { 498 return false 499 } 500 if !p.Payload.Equals(o.Payload) { 501 return false 502 } 503 if len(p.Interims) != len(o.Interims) { 504 return false 505 } 506 for i, inter := range p.Interims { 507 if inter != o.Interims[i] { 508 return false 509 } 510 } 511 if p.Inclusion != o.Inclusion { 512 return false 513 } 514 if !bytes.Equal(p.Flags, o.Flags) { 515 return false 516 } 517 if p.Steps != o.Steps { 518 return false 519 } 520 return true 521 } 522 523 // TrieBatchProof is a struct that holds the proofs for several keys 524 // 525 // so there is no need for two calls (read, proofs) 526 type TrieBatchProof struct { 527 Proofs []*TrieProof 528 } 529 530 // NewTrieBatchProof creates a new instance of BatchProof 531 func NewTrieBatchProof() *TrieBatchProof { 532 bp := new(TrieBatchProof) 533 bp.Proofs = make([]*TrieProof, 0) 534 return bp 535 } 536 537 // NewTrieBatchProofWithEmptyProofs creates an instance of Batchproof 538 // filled with n newly created proofs (empty) 539 func NewTrieBatchProofWithEmptyProofs(numberOfProofs int) *TrieBatchProof { 540 bp := new(TrieBatchProof) 541 bp.Proofs = make([]*TrieProof, numberOfProofs) 542 for i := 0; i < numberOfProofs; i++ { 543 bp.Proofs[i] = NewTrieProof() 544 } 545 return bp 546 } 547 548 // Size returns the number of proofs 549 func (bp *TrieBatchProof) Size() int { 550 return len(bp.Proofs) 551 } 552 553 // Paths returns the slice of paths for this batch proof 554 func (bp *TrieBatchProof) Paths() []Path { 555 paths := make([]Path, len(bp.Proofs)) 556 for i, p := range bp.Proofs { 557 paths[i] = p.Path 558 } 559 return paths 560 } 561 562 // Payloads returns the slice of paths for this batch proof 563 func (bp *TrieBatchProof) Payloads() []*Payload { 564 payloads := make([]*Payload, len(bp.Proofs)) 565 for i, p := range bp.Proofs { 566 payloads[i] = p.Payload 567 } 568 return payloads 569 } 570 571 func (bp *TrieBatchProof) String() string { 572 res := fmt.Sprintf("trie batch proof includes %d proofs: \n", bp.Size()) 573 for _, proof := range bp.Proofs { 574 res = res + "\n" + proof.String() 575 } 576 return res 577 } 578 579 // AppendProof adds a proof to the batch proof 580 func (bp *TrieBatchProof) AppendProof(p *TrieProof) { 581 bp.Proofs = append(bp.Proofs, p) 582 } 583 584 // MergeInto adds all of its proofs into the dest batch proof 585 func (bp *TrieBatchProof) MergeInto(dest *TrieBatchProof) { 586 for _, p := range bp.Proofs { 587 dest.AppendProof(p) 588 } 589 } 590 591 // Equals compares this batch proof to another batch proof 592 func (bp *TrieBatchProof) Equals(o *TrieBatchProof) bool { 593 if o == nil { 594 return false 595 } 596 if len(bp.Proofs) != len(o.Proofs) { 597 return false 598 } 599 for i, proof := range bp.Proofs { 600 if !proof.Equals(o.Proofs[i]) { 601 return false 602 } 603 } 604 return true 605 }