github.com/koko1123/flow-go-1@v0.29.6/ledger/common/proof/proof.go (about) 1 package proof 2 3 import ( 4 "github.com/koko1123/flow-go-1/ledger" 5 "github.com/koko1123/flow-go-1/ledger/common/bitutils" 6 "github.com/koko1123/flow-go-1/ledger/common/hash" 7 ) 8 9 // TODO move this to proof itself 10 11 // VerifyTrieProof verifies the proof, by constructing all the 12 // hash from the leaf to the root and comparing the rootHash 13 func VerifyTrieProof(p *ledger.TrieProof, expectedState ledger.State) bool { 14 treeHeight := ledger.NodeMaxHeight 15 leafHeight := treeHeight - int(p.Steps) // p.Steps is the number of edges we are traversing until we hit the compactified leaf. 16 if !(0 <= leafHeight && leafHeight <= treeHeight) { // sanity check 17 return false 18 } 19 // We start with the leaf and hash our way upwards towards the root 20 proofIndex := len(p.Interims) - 1 // the index of the last non-default value furthest down the tree (-1 if there is none) 21 computed := ledger.ComputeCompactValue(hash.Hash(p.Path), p.Payload.Value(), leafHeight) // we first compute the hash of the compact leaf (at height leafHeight) 22 for h := leafHeight + 1; h <= treeHeight; h++ { // then, we hash our way upwards until we hit the root (at height `treeHeight`) 23 // we are currently at a node n (initially the leaf). In this iteration, we want to compute the 24 // parent's hash. Here, h is the height of the parent, whose hash want to compute. 25 // The parent has two children: child n, whose hash we have already computed (aka `computed`); 26 // and the sibling to node n, whose hash (aka `siblingHash`) must be defined by the Proof. 27 28 var siblingHash hash.Hash 29 flag := bitutils.ReadBit(p.Flags, treeHeight-h) 30 31 if flag == 1 { // if flag is set, siblingHash is stored in the proof 32 if proofIndex < 0 { // proof invalid: too few values 33 return false 34 } 35 siblingHash = p.Interims[proofIndex] 36 proofIndex-- 37 } else { // otherwise, siblingHash is a default hash 38 siblingHash = ledger.GetDefaultHashForHeight(h - 1) 39 } 40 41 bit := bitutils.ReadBit(p.Path[:], treeHeight-h) 42 // hashing is order dependent 43 if bit == 1 { // we hash our way up to the parent along the parent's right branch 44 computed = hash.HashInterNode(siblingHash, computed) 45 } else { // we hash our way up to the parent along the parent's left branch 46 computed = hash.HashInterNode(computed, siblingHash) 47 } 48 } 49 return (computed == hash.Hash(expectedState)) == p.Inclusion 50 } 51 52 // VerifyTrieBatchProof verifies all the proof inside the batchproof 53 func VerifyTrieBatchProof(bp *ledger.TrieBatchProof, expectedState ledger.State) bool { 54 for _, p := range bp.Proofs { 55 // any invalid proof 56 if !VerifyTrieProof(p, expectedState) { 57 return false 58 } 59 } 60 return true 61 }