Skip to content

Commit

Permalink
merkle: Add ConvertProofOrdering
Browse files Browse the repository at this point in the history
  • Loading branch information
lukechampine committed Oct 30, 2020
1 parent cb6b17f commit 31c012b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
14 changes: 14 additions & 0 deletions merkle/merkle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ import (
"lukechampine.com/us/renterhost"
)

func TestConvertProofOrdering(t *testing.T) {
var sector [renterhost.SectorSize]byte
frand.Read(sector[:])
for i := 0; i < 10; i++ {
index := frand.Intn(SegmentsPerSector)
proof := ConvertProofOrdering(BuildProof(&sector, index, index+1, nil), index)
_, exp := crypto.MerkleProof(sector[:], uint64(index))

if !reflect.DeepEqual(proof, exp) {
t.Fatalf("mismatch: %v\n%v\n%v", index, proof, exp)
}
}
}

func TestProofSize(t *testing.T) {
tests := []struct {
n, start, end int
Expand Down
20 changes: 20 additions & 0 deletions merkle/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,3 +478,23 @@ func NewRangeProofVerifier(start, end int) *RangeProofVerifier {
end: end,
}
}

// ConvertProofOrdering converts "left-to-right" proofs into the "leaf-to-root"
// ordering used in consensus storage proofs.
func ConvertProofOrdering(proof []crypto.Hash, index int) []crypto.Hash {
// strategy: split proof into lefts and rights, then iterate over bits in
// leaf-to-root order, selecting either a left or right hash as appropriate.
lefts := proof[:bits.OnesCount(uint(index))]
rights := proof[len(lefts):]
reordered := make([]crypto.Hash, 0, len(proof))
for i := 0; len(reordered) < len(proof); i++ {
if index&(1<<i) != 0 {
reordered = append(reordered, lefts[len(lefts)-1])
lefts = lefts[:len(lefts)-1]
} else if len(rights) > 0 {
reordered = append(reordered, rights[0])
rights = rights[1:]
}
}
return reordered
}

0 comments on commit 31c012b

Please sign in to comment.