Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions demo/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ const HashSize = sha256.Size

type HashValue = [HashSize]byte

func HashEmpty() HashValue {
h := sha256.New()
var ret HashValue
h.Sum(ret[:0])
return ret
}

func HashLeaf(b []byte) HashValue {
h := sha256.New()
h.Write([]byte{0})
Expand All @@ -30,9 +37,12 @@ func HashNode(left, right *HashValue) HashValue {
}

func IsValidSubtree(start, end int) bool {
if 0 > start || start >= end {
if 0 > start || start > end {
return false
}
if start == end {
return true
}
ceil := uint(1) << (bits.UintSize - bits.LeadingZeros(uint(end-start-1)))
return uint(start)&(ceil-1) == 0
}
Expand Down Expand Up @@ -74,6 +84,9 @@ func (mt *MerkleTree) SubtreeHash(start, end int) (HashValue, error) {
if end > mt.Size() {
return HashValue{}, fmt.Errorf("subtree [%d, %d) contains more elements than tree of size %d", start, end, mt.Size())
}
if start == end {
return HashEmpty(), nil
}
// Start at the largest complete subtree on the right edge.
last := end - 1
level := bits.TrailingZeros(^uint(last - start))
Expand Down Expand Up @@ -138,6 +151,9 @@ func (mt *MerkleTree) SubtreeConsistencyProof(start, end, n int) ([]byte, error)
if n > mt.Size() {
return nil, fmt.Errorf("tree of size %d is larger than the Merkle Tree of size %d", n, mt.Size())
}
if start == end {
return nil, nil
}
return mt.subtreeSubproof(start, end, 0, n, true)
}

Expand Down Expand Up @@ -193,14 +209,14 @@ func (mt *MerkleTree) subtreeSubproof(start, end, lo, hi int, known bool) ([]byt
}

func SubtreesForInterval(start, end int) (start1, end1, start2, end2 int, err error) {
if 0 > start || start >= end {
if 0 > start || start > end {
err = fmt.Errorf("invalid interval [%d, %d)", start, end)
return
}
if end-start == 1 {
if end-start <= 1 {
start1 = start
start2 = start
end1 = end
start2 = end
end2 = end
return
}
Expand Down
3 changes: 2 additions & 1 deletion demo/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func TestSubtreesForInterval(t *testing.T) {
start1, end1 int
start2, end2 int
}{
{start: 8, end: 9, start1: 8, end1: 9, start2: 8, end2: 9},
{start: 9, end: 9, start1: 9, end1: 9, start2: 9, end2: 9},
{start: 8, end: 9, start1: 8, end1: 9, start2: 9, end2: 9},
{start: 5, end: 13, start1: 4, end1: 8, start2: 8, end2: 13},
{start: 7, end: 9, start1: 7, end1: 8, start2: 8, end2: 9},
}
Expand Down
26 changes: 11 additions & 15 deletions demo/vectors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ func writeProofLine(w io.Writer, prefix string, proof []byte) {
func TestSubtreeHashVectors(t *testing.T) {
tree := subtreeVectorTree()
h := sha256.New()
for end := 1; end <= subtreeVectorMax; end++ {
for start := 0; start < end; start++ {
for end := 0; end <= subtreeVectorMax; end++ {
for start := 0; start <= end; start++ {
if !IsValidSubtree(start, end) {
continue
}
Expand All @@ -50,7 +50,7 @@ func TestSubtreeHashVectors(t *testing.T) {
fmt.Fprintf(h, "[%d, %d) %x\n", start, end, subtreeHash[:])
}
}
const want = "94a95384a8c69acea9b50d035a58285b3a777cb7a724005faa5e1f1e1190007f"
const want = "b82806ad4265bb151c1119c0f4db437bb4d1a1f887b3a7fba1cd4ebf552e3e81"
if got := fmt.Sprintf("%x", h.Sum(nil)); got != want {
t.Errorf("subtree hash vector = %s, want %s", got, want)
}
Expand All @@ -59,8 +59,8 @@ func TestSubtreeHashVectors(t *testing.T) {
func TestSubtreeInclusionProofVectors(t *testing.T) {
tree := subtreeVectorTree()
h := sha256.New()
for end := 1; end <= subtreeVectorMax; end++ {
for start := 0; start < end; start++ {
for end := 0; end <= subtreeVectorMax; end++ {
for start := 0; start <= end; start++ {
if !IsValidSubtree(start, end) {
continue
}
Expand All @@ -83,8 +83,8 @@ func TestSubtreeConsistencyProofVectors(t *testing.T) {
tree := subtreeVectorTree()
h := sha256.New()
for n := 0; n <= subtreeVectorMax; n++ {
for end := 1; end <= n; end++ {
for start := 0; start < end; start++ {
for end := 0; end <= n; end++ {
for start := 0; start <= end; start++ {
if !IsValidSubtree(start, end) {
continue
}
Expand All @@ -96,28 +96,24 @@ func TestSubtreeConsistencyProofVectors(t *testing.T) {
}
}
}
const want = "c586ebbb73a5621baf2140095d87dde934e3b6503a562a1a5215b8209edd083d"
const want = "10fa99b37bf9bf9ffa26b412fbd98bd75363256d0b75d61bc4538b9c9c5a0a74"
if got := fmt.Sprintf("%x", h.Sum(nil)); got != want {
t.Errorf("subtree consistency proof vector = %s, want %s", got, want)
}
}

func TestEfficientCoveringSubtreeVectors(t *testing.T) {
h := sha256.New()
for end := 1; end <= subtreeVectorMax; end++ {
for start := 0; start < end; start++ {
if IsValidSubtree(start, end) {
fmt.Fprintf(h, "[%d, %d)\n", start, end)
continue
}
for end := 0; end <= subtreeVectorMax; end++ {
for start := 0; start <= end; start++ {
start1, end1, start2, end2, err := SubtreesForInterval(start, end)
if err != nil {
t.Fatalf("SubtreesForInterval(%d, %d): %v", start, end, err)
}
fmt.Fprintf(h, "[%d, %d) [%d, %d)\n", start1, end1, start2, end2)
}
}
const want = "e0aecb912a10c57d753b6ecc64db73217f9bc4ed10fcb4e9062be3b6fbe1ebfd"
const want = "7fd9c8b926e9d2b5cf831560e8ce295a5ef97ad5c5ede4ea0dea28a8c8fc8bb0"
if got := fmt.Sprintf("%x", h.Sum(nil)); got != want {
t.Errorf("efficient covering subtree vector = %s, want %s", got, want)
}
Expand Down
Loading
Loading