gitlab.com/SiaPrime/SiaPrime@v1.4.1/crypto/merkle.go (about) 1 package crypto 2 3 import ( 4 "bytes" 5 6 "gitlab.com/NebulousLabs/merkletree" 7 8 "gitlab.com/SiaPrime/SiaPrime/encoding" 9 ) 10 11 const ( 12 // SegmentSize is the chunk size that is used when taking the Merkle root 13 // of a file. 64 is chosen because bandwidth is scarce and it optimizes for 14 // the smallest possible storage proofs. Using a larger base, even 256 15 // bytes, would result in substantially faster hashing, but the bandwidth 16 // tradeoff was deemed to be more important, as blockchain space is scarce. 17 SegmentSize = 64 18 ) 19 20 // MerkleTree wraps merkletree.Tree, changing some of the function definitions 21 // to assume sia-specific constants and return sia-specific types. 22 type MerkleTree struct { 23 merkletree.Tree 24 } 25 26 // NewTree returns a MerkleTree, which can be used for getting Merkle roots and 27 // Merkle proofs on data. See merkletree.Tree for more details. 28 func NewTree() *MerkleTree { 29 return &MerkleTree{*merkletree.New(NewHash())} 30 } 31 32 // PushObject encodes and adds the hash of the encoded object to the tree as a 33 // leaf. 34 func (t *MerkleTree) PushObject(obj interface{}) { 35 t.Push(encoding.Marshal(obj)) 36 } 37 38 // Root is a redefinition of merkletree.Tree.Root, returning a Hash instead of 39 // a []byte. 40 func (t *MerkleTree) Root() (h Hash) { 41 copy(h[:], t.Tree.Root()) 42 return 43 } 44 45 // CachedMerkleTree wraps merkletree.CachedTree, changing some of the function 46 // definitions to assume sia-specific constants and return sia-specific types. 47 type CachedMerkleTree struct { 48 merkletree.CachedTree 49 } 50 51 // NewCachedTree returns a CachedMerkleTree, which can be used for getting 52 // Merkle roots and proofs from data that has cached subroots. See 53 // merkletree.CachedTree for more details. 54 func NewCachedTree(height uint64) *CachedMerkleTree { 55 return &CachedMerkleTree{*merkletree.NewCachedTree(NewHash(), height)} 56 } 57 58 // Prove is a redefinition of merkletree.CachedTree.Prove, so that Sia-specific 59 // types are used instead of the generic types used by the parent package. The 60 // base is not a return value because the base is used as input. 61 func (ct *CachedMerkleTree) Prove(base []byte, cachedHashSet []Hash) []Hash { 62 // Turn the input in to a proof set that will be recognized by the high 63 // level tree. 64 cachedProofSet := make([][]byte, len(cachedHashSet)+1) 65 cachedProofSet[0] = base 66 for i := range cachedHashSet { 67 cachedProofSet[i+1] = cachedHashSet[i][:] 68 } 69 _, proofSet, _, _ := ct.CachedTree.Prove(cachedProofSet) 70 71 // convert proofSet to base and hashSet 72 hashSet := make([]Hash, len(proofSet)-1) 73 for i, proof := range proofSet[1:] { 74 copy(hashSet[i][:], proof) 75 } 76 return hashSet 77 } 78 79 // Push is a redefinition of merkletree.CachedTree.Push, with the added type 80 // safety of only accepting a hash. 81 func (ct *CachedMerkleTree) Push(h Hash) { 82 ct.CachedTree.Push(h[:]) 83 } 84 85 // PushSubTree is a redefinition of merkletree.CachedTree.PushSubTree, with the 86 // added type safety of only accepting a hash. 87 func (ct *CachedMerkleTree) PushSubTree(height int, h Hash) error { 88 return ct.CachedTree.PushSubTree(height, h[:]) 89 } 90 91 // Root is a redefinition of merkletree.CachedTree.Root, returning a Hash 92 // instead of a []byte. 93 func (ct *CachedMerkleTree) Root() (h Hash) { 94 copy(h[:], ct.CachedTree.Root()) 95 return 96 } 97 98 // CalculateLeaves calculates the number of leaves that would be pushed from 99 // data of size 'dataSize'. 100 func CalculateLeaves(dataSize uint64) uint64 { 101 numSegments := dataSize / SegmentSize 102 if dataSize == 0 || dataSize%SegmentSize != 0 { 103 numSegments++ 104 } 105 return numSegments 106 } 107 108 // MerkleRoot returns the Merkle root of the input data. 109 func MerkleRoot(b []byte) Hash { 110 t := NewTree() 111 buf := bytes.NewBuffer(b) 112 for buf.Len() > 0 { 113 t.Push(buf.Next(SegmentSize)) 114 } 115 return t.Root() 116 } 117 118 // MerkleProof builds a Merkle proof that the data at segment 'proofIndex' is a 119 // part of the Merkle root formed by 'b'. 120 // 121 // MerkleProof is NOT equivalent to MerkleRangeProof for a single segment. 122 func MerkleProof(b []byte, proofIndex uint64) (base []byte, hashSet []Hash) { 123 // Create the tree. 124 t := NewTree() 125 t.SetIndex(proofIndex) 126 127 // Fill the tree. 128 buf := bytes.NewBuffer(b) 129 for buf.Len() > 0 { 130 t.Push(buf.Next(SegmentSize)) 131 } 132 133 // Get the proof and convert it to a base + hash set. 134 _, proof, _, _ := t.Prove() 135 if len(proof) == 0 { 136 // There's no proof, because there's no data. Return blank values. 137 return nil, nil 138 } 139 140 base = proof[0] 141 hashSet = make([]Hash, len(proof)-1) 142 for i, p := range proof[1:] { 143 copy(hashSet[i][:], p) 144 } 145 return base, hashSet 146 } 147 148 // VerifySegment will verify that a segment, given the proof, is a part of a 149 // Merkle root. 150 // 151 // VerifySegment is NOT equivalent to VerifyRangeProof for a single segment. 152 func VerifySegment(base []byte, hashSet []Hash, numSegments, proofIndex uint64, root Hash) bool { 153 // convert base and hashSet to proofSet 154 proofSet := make([][]byte, len(hashSet)+1) 155 proofSet[0] = base 156 for i := range hashSet { 157 proofSet[i+1] = hashSet[i][:] 158 } 159 return merkletree.VerifyProof(NewHash(), root[:], proofSet, proofIndex, numSegments) 160 } 161 162 // MerkleRangeProof builds a Merkle proof for the segment range [start,end). 163 // 164 // MerkleRangeProof for a single segment is NOT equivalent to MerkleProof. 165 func MerkleRangeProof(b []byte, start, end int) []Hash { 166 proof, _ := merkletree.BuildRangeProof(start, end, merkletree.NewReaderSubtreeHasher(bytes.NewReader(b), SegmentSize, NewHash())) 167 proofHashes := make([]Hash, len(proof)) 168 for i := range proofHashes { 169 copy(proofHashes[i][:], proof[i]) 170 } 171 return proofHashes 172 } 173 174 // VerifyRangeProof verifies a proof produced by MerkleRangeProof. 175 // 176 // VerifyRangeProof for a single segment is NOT equivalent to VerifySegment. 177 func VerifyRangeProof(segments []byte, proof []Hash, start, end int, root Hash) bool { 178 proofBytes := make([][]byte, len(proof)) 179 for i := range proof { 180 proofBytes[i] = proof[i][:] 181 } 182 result, _ := merkletree.VerifyRangeProof(merkletree.NewReaderLeafHasher(bytes.NewReader(segments), NewHash(), SegmentSize), NewHash(), start, end, proofBytes, root[:]) 183 return result 184 } 185 186 // MerkleSectorRangeProof builds a Merkle proof for the sector range [start,end). 187 func MerkleSectorRangeProof(roots []Hash, start, end int) []Hash { 188 leafHashes := make([][]byte, len(roots)) 189 for i := range leafHashes { 190 leafHashes[i] = roots[i][:] 191 } 192 sh := merkletree.NewCachedSubtreeHasher(leafHashes, NewHash()) 193 proof, _ := merkletree.BuildRangeProof(start, end, sh) 194 proofHashes := make([]Hash, len(proof)) 195 for i := range proofHashes { 196 copy(proofHashes[i][:], proof[i]) 197 } 198 return proofHashes 199 } 200 201 // VerifySectorRangeProof verifies a proof produced by MerkleSectorRangeProof. 202 func VerifySectorRangeProof(roots []Hash, proof []Hash, start, end int, root Hash) bool { 203 leafHashes := make([][]byte, len(roots)) 204 for i := range leafHashes { 205 leafHashes[i] = roots[i][:] 206 } 207 lh := merkletree.NewCachedLeafHasher(leafHashes) 208 proofBytes := make([][]byte, len(proof)) 209 for i := range proof { 210 proofBytes[i] = proof[i][:] 211 } 212 result, _ := merkletree.VerifyRangeProof(lh, NewHash(), start, end, proofBytes, root[:]) 213 return result 214 } 215 216 // A ProofRange is a contiguous range of segments or sectors. 217 type ProofRange = merkletree.LeafRange 218 219 // MerkleDiffProof builds a Merkle proof for multiple segment ranges. 220 func MerkleDiffProof(ranges []ProofRange, numLeaves uint64, updatedSectors [][]byte, sectorRoots []Hash) []Hash { 221 leafHashes := make([][]byte, len(sectorRoots)) 222 for i := range leafHashes { 223 leafHashes[i] = sectorRoots[i][:] 224 } 225 sh := merkletree.NewCachedSubtreeHasher(leafHashes, NewHash()) // TODO: needs to include updatedSectors somehow 226 proof, _ := merkletree.BuildDiffProof(ranges, sh, numLeaves) 227 proofHashes := make([]Hash, len(proof)) 228 for i := range proofHashes { 229 copy(proofHashes[i][:], proof[i]) 230 } 231 return proofHashes 232 } 233 234 // VerifyDiffProof verifies a proof produced by MerkleDiffProof. 235 func VerifyDiffProof(ranges []ProofRange, numLeaves uint64, proofHashes, leafHashes []Hash, root Hash) bool { 236 proofBytes := make([][]byte, len(proofHashes)) 237 for i := range proofHashes { 238 proofBytes[i] = proofHashes[i][:] 239 } 240 leafBytes := make([][]byte, len(leafHashes)) 241 for i := range leafHashes { 242 leafBytes[i] = leafHashes[i][:] 243 } 244 rootBytes := root[:] 245 if root == (Hash{}) { 246 rootBytes = nil // empty trees hash to nil, not 32 zeros 247 } 248 lh := merkletree.NewCachedLeafHasher(leafBytes) 249 ok, _ := merkletree.VerifyDiffProof(lh, numLeaves, NewHash(), ranges, proofBytes, rootBytes) 250 return ok 251 }