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  }