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