github.com/okex/exchain@v1.8.0/libs/tendermint/crypto/merkle/simple_proof.go (about) 1 package merkle 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/tendermint/go-amino" 7 8 "github.com/pkg/errors" 9 10 "github.com/okex/exchain/libs/tendermint/crypto/tmhash" 11 ) 12 13 const ( 14 // MaxAunts is the maximum number of aunts that can be included in a SimpleProof. 15 // This corresponds to a tree of size 2^100, which should be sufficient for all conceivable purposes. 16 // This maximum helps prevent Denial-of-Service attacks by limitting the size of the proofs. 17 MaxAunts = 100 18 ) 19 20 // SimpleProof represents a simple Merkle proof. 21 // NOTE: The convention for proofs is to include leaf hashes but to 22 // exclude the root hash. 23 // This convention is implemented across IAVL range proofs as well. 24 // Keep this consistent unless there's a very good reason to change 25 // everything. This also affects the generalized proof system as 26 // well. 27 type SimpleProof struct { 28 Total int `json:"total"` // Total number of items. 29 Index int `json:"index"` // Index of item to prove. 30 LeafHash []byte `json:"leaf_hash"` // Hash of item value. 31 Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. 32 } 33 34 func (sp *SimpleProof) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 35 var dataLen uint64 = 0 36 var subData []byte 37 38 for { 39 data = data[dataLen:] 40 41 if len(data) == 0 { 42 break 43 } 44 45 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 46 if err != nil { 47 return err 48 } 49 data = data[1:] 50 51 if aminoType == amino.Typ3_ByteLength { 52 var n int 53 dataLen, n, err = amino.DecodeUvarint(data) 54 if err != nil { 55 return err 56 } 57 58 data = data[n:] 59 if len(data) < int(dataLen) { 60 return fmt.Errorf("not enough data for field") 61 } 62 subData = data[:dataLen] 63 } 64 65 switch pos { 66 case 1: 67 uvint, n, err := amino.DecodeUvarint(data) 68 if err != nil { 69 return err 70 } 71 sp.Total = int(uvint) 72 dataLen = uint64(n) 73 case 2: 74 var n int 75 sp.Index, n, err = amino.DecodeInt(data) 76 if err != nil { 77 return err 78 } 79 dataLen = uint64(n) 80 case 3: 81 sp.LeafHash = make([]byte, dataLen) 82 copy(sp.LeafHash, subData) 83 case 4: 84 var aunt []byte 85 if dataLen > 0 { 86 aunt = make([]byte, dataLen) 87 copy(aunt, subData) 88 } 89 sp.Aunts = append(sp.Aunts, aunt) 90 default: 91 return fmt.Errorf("unexpect feild num %d", pos) 92 } 93 } 94 return nil 95 } 96 97 // SimpleProofsFromByteSlices computes inclusion proof for given items. 98 // proofs[0] is the proof for items[0]. 99 func SimpleProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*SimpleProof) { 100 trails, rootSPN := trailsFromByteSlices(items) 101 rootHash = rootSPN.Hash 102 proofs = make([]*SimpleProof, len(items)) 103 for i, trail := range trails { 104 proofs[i] = &SimpleProof{ 105 Total: len(items), 106 Index: i, 107 LeafHash: trail.Hash, 108 Aunts: trail.FlattenAunts(), 109 } 110 } 111 return 112 } 113 114 // SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values 115 // in the underlying key-value pairs. 116 // The keys are sorted before the proofs are computed. 117 func SimpleProofsFromMap(m map[string][]byte) (rootHash []byte, proofs map[string]*SimpleProof, keys []string) { 118 sm := newSimpleMap() 119 for k, v := range m { 120 sm.Set(k, v) 121 } 122 sm.Sort() 123 kvs := sm.kvs 124 kvsBytes := make([][]byte, len(kvs)) 125 for i, kvp := range kvs { 126 kvsBytes[i] = KVPair(kvp).Bytes() 127 } 128 129 rootHash, proofList := SimpleProofsFromByteSlices(kvsBytes) 130 proofs = make(map[string]*SimpleProof) 131 keys = make([]string, len(proofList)) 132 for i, kvp := range kvs { 133 proofs[string(kvp.Key)] = proofList[i] 134 keys[i] = string(kvp.Key) 135 } 136 return 137 } 138 139 // Verify that the SimpleProof proves the root hash. 140 // Check sp.Index/sp.Total manually if needed 141 func (sp *SimpleProof) Verify(rootHash []byte, leaf []byte) error { 142 leafHash := leafHash(leaf) 143 if sp.Total < 0 { 144 return errors.New("proof total must be positive") 145 } 146 if sp.Index < 0 { 147 return errors.New("proof index cannot be negative") 148 } 149 if !bytes.Equal(sp.LeafHash, leafHash) { 150 return errors.Errorf("invalid leaf hash: wanted %X got %X", leafHash, sp.LeafHash) 151 } 152 computedHash := sp.ComputeRootHash() 153 if !bytes.Equal(computedHash, rootHash) { 154 return errors.Errorf("invalid root hash: wanted %X got %X", rootHash, computedHash) 155 } 156 return nil 157 } 158 159 // Compute the root hash given a leaf hash. Does not verify the result. 160 func (sp *SimpleProof) ComputeRootHash() []byte { 161 return computeHashFromAunts( 162 sp.Index, 163 sp.Total, 164 sp.LeafHash, 165 sp.Aunts, 166 ) 167 } 168 169 // String implements the stringer interface for SimpleProof. 170 // It is a wrapper around StringIndented. 171 func (sp *SimpleProof) String() string { 172 return sp.StringIndented("") 173 } 174 175 // StringIndented generates a canonical string representation of a SimpleProof. 176 func (sp *SimpleProof) StringIndented(indent string) string { 177 return fmt.Sprintf(`SimpleProof{ 178 %s Aunts: %X 179 %s}`, 180 indent, sp.Aunts, 181 indent) 182 } 183 184 // ValidateBasic performs basic validation. 185 // NOTE: it expects the LeafHash and the elements of Aunts to be of size tmhash.Size, 186 // and it expects at most MaxAunts elements in Aunts. 187 func (sp *SimpleProof) ValidateBasic() error { 188 if sp.Total < 0 { 189 return errors.New("negative Total") 190 } 191 if sp.Index < 0 { 192 return errors.New("negative Index") 193 } 194 if len(sp.LeafHash) != tmhash.Size { 195 return errors.Errorf("expected LeafHash size to be %d, got %d", tmhash.Size, len(sp.LeafHash)) 196 } 197 if len(sp.Aunts) > MaxAunts { 198 return errors.Errorf("expected no more than %d aunts, got %d", MaxAunts, len(sp.Aunts)) 199 } 200 for i, auntHash := range sp.Aunts { 201 if len(auntHash) != tmhash.Size { 202 return errors.Errorf("expected Aunts#%d size to be %d, got %d", i, tmhash.Size, len(auntHash)) 203 } 204 } 205 return nil 206 } 207 208 // Use the leafHash and innerHashes to get the root merkle hash. 209 // If the length of the innerHashes slice isn't exactly correct, the result is nil. 210 // Recursive impl. 211 func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { 212 if index >= total || index < 0 || total <= 0 { 213 return nil 214 } 215 switch total { 216 case 0: 217 panic("Cannot call computeHashFromAunts() with 0 total") 218 case 1: 219 if len(innerHashes) != 0 { 220 return nil 221 } 222 return leafHash 223 default: 224 if len(innerHashes) == 0 { 225 return nil 226 } 227 numLeft := getSplitPoint(total) 228 if index < numLeft { 229 leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) 230 if leftHash == nil { 231 return nil 232 } 233 return innerHash(leftHash, innerHashes[len(innerHashes)-1]) 234 } 235 rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) 236 if rightHash == nil { 237 return nil 238 } 239 return innerHash(innerHashes[len(innerHashes)-1], rightHash) 240 } 241 } 242 243 // SimpleProofNode is a helper structure to construct merkle proof. 244 // The node and the tree is thrown away afterwards. 245 // Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. 246 // node.Parent.Hash = hash(node.Hash, node.Right.Hash) or 247 // hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. 248 type SimpleProofNode struct { 249 Hash []byte 250 Parent *SimpleProofNode 251 Left *SimpleProofNode // Left sibling (only one of Left,Right is set) 252 Right *SimpleProofNode // Right sibling (only one of Left,Right is set) 253 } 254 255 // FlattenAunts will return the inner hashes for the item corresponding to the leaf, 256 // starting from a leaf SimpleProofNode. 257 func (spn *SimpleProofNode) FlattenAunts() [][]byte { 258 // Nonrecursive impl. 259 innerHashes := [][]byte{} 260 for spn != nil { 261 switch { 262 case spn.Left != nil: 263 innerHashes = append(innerHashes, spn.Left.Hash) 264 case spn.Right != nil: 265 innerHashes = append(innerHashes, spn.Right.Hash) 266 default: 267 break 268 } 269 spn = spn.Parent 270 } 271 return innerHashes 272 } 273 274 // trails[0].Hash is the leaf hash for items[0]. 275 // trails[i].Parent.Parent....Parent == root for all i. 276 func trailsFromByteSlices(items [][]byte) (trails []*SimpleProofNode, root *SimpleProofNode) { 277 // Recursive impl. 278 switch len(items) { 279 case 0: 280 return nil, nil 281 case 1: 282 trail := &SimpleProofNode{leafHash(items[0]), nil, nil, nil} 283 return []*SimpleProofNode{trail}, trail 284 default: 285 k := getSplitPoint(len(items)) 286 lefts, leftRoot := trailsFromByteSlices(items[:k]) 287 rights, rightRoot := trailsFromByteSlices(items[k:]) 288 rootHash := innerHash(leftRoot.Hash, rightRoot.Hash) 289 root := &SimpleProofNode{rootHash, nil, nil, nil} 290 leftRoot.Parent = root 291 leftRoot.Right = rightRoot 292 rightRoot.Parent = root 293 rightRoot.Left = leftRoot 294 return append(lefts, rights...), root 295 } 296 }