Skip to content

Commit

Permalink
Fix new history tree version
Browse files Browse the repository at this point in the history
Co-authored-by: Gabriel Díaz <[email protected]>
  • Loading branch information
aalda and gdiazlo committed Feb 25, 2019
1 parent 6aa6af5 commit f0effb9
Show file tree
Hide file tree
Showing 46 changed files with 1,524 additions and 3,091 deletions.
104 changes: 72 additions & 32 deletions balloon/history/navigation/position_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,24 @@ func TestIsLeaf(t *testing.T) {
func TestLeft(t *testing.T) {

testCases := []struct {
version uint64
position *Position
expectedLeft *Position
}{
{0, NewPosition(0, 0), nil},
{1, NewPosition(0, 0), nil},
{1, NewPosition(1, 0), nil},
{1, NewPosition(0, 1), NewPosition(0, 0)},
{2, NewPosition(0, 0), nil},
{2, NewPosition(1, 0), nil},
{2, NewPosition(2, 0), nil},
{2, NewPosition(0, 1), NewPosition(0, 0)},
{2, NewPosition(2, 1), NewPosition(2, 0)}, // TODO check invalid positions like (1,1)?
{3, NewPosition(0, 0), nil},
{3, NewPosition(1, 0), nil},
{3, NewPosition(2, 0), nil},
{3, NewPosition(0, 1), NewPosition(0, 0)},
{3, NewPosition(2, 1), NewPosition(2, 0)},
{3, NewPosition(0, 2), NewPosition(0, 1)},
{NewPosition(0, 0), nil},
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(0, 1), NewPosition(0, 0)},
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(2, 0), nil},
{NewPosition(0, 1), NewPosition(0, 0)},
{NewPosition(2, 1), NewPosition(2, 0)}, // TODO check invalid positions like (1,1)?
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(2, 0), nil},
{NewPosition(0, 1), NewPosition(0, 0)},
{NewPosition(2, 1), NewPosition(2, 0)},
{NewPosition(0, 2), NewPosition(0, 1)},
}

for i, c := range testCases {
Expand All @@ -98,29 +97,70 @@ func TestLeft(t *testing.T) {
func TestRight(t *testing.T) {

testCases := []struct {
version uint64
position *Position
expectedRight *Position
}{
{0, NewPosition(0, 0), nil},
{1, NewPosition(0, 0), nil},
{1, NewPosition(1, 0), nil},
{1, NewPosition(0, 1), NewPosition(1, 0)},
{2, NewPosition(0, 0), nil},
{2, NewPosition(1, 0), nil},
{2, NewPosition(2, 0), nil},
{2, NewPosition(0, 1), NewPosition(1, 0)},
{2, NewPosition(2, 1), NewPosition(3, 0)},
{3, NewPosition(0, 0), nil},
{3, NewPosition(1, 0), nil},
{3, NewPosition(2, 0), nil},
{3, NewPosition(0, 1), NewPosition(1, 0)},
{3, NewPosition(2, 1), NewPosition(3, 0)},
{3, NewPosition(0, 2), NewPosition(2, 1)},
{NewPosition(0, 0), nil},
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(0, 1), NewPosition(1, 0)},
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(2, 0), nil},
{NewPosition(0, 1), NewPosition(1, 0)},
{NewPosition(2, 1), NewPosition(3, 0)},
{NewPosition(0, 0), nil},
{NewPosition(1, 0), nil},
{NewPosition(2, 0), nil},
{NewPosition(0, 1), NewPosition(1, 0)},
{NewPosition(2, 1), NewPosition(3, 0)},
{NewPosition(0, 2), NewPosition(2, 1)},
}

for i, c := range testCases {
right := c.position.Right()
require.Equalf(t, c.expectedRight, right, "The right positions should match for test case %d", i)
}
}

func TestFirstDescendant(t *testing.T) {

testCases := []struct {
position *Position
expectedPos *Position
}{
{NewPosition(0, 0), NewPosition(0, 0)},
{NewPosition(1, 0), NewPosition(1, 0)},
{NewPosition(0, 1), NewPosition(0, 0)},
{NewPosition(2, 0), NewPosition(2, 0)},
{NewPosition(2, 1), NewPosition(2, 0)},
{NewPosition(0, 2), NewPosition(0, 0)},
}

for i, c := range testCases {
first := c.position.FirstDescendant()
require.Equalf(t, c.expectedPos, first, "The first descentant position should match for test case %d", i)
}

}

func TestLastDescendant(t *testing.T) {

testCases := []struct {
position *Position
expectedPos *Position
}{
{NewPosition(0, 0), NewPosition(0, 0)},
{NewPosition(1, 0), NewPosition(1, 0)},
{NewPosition(0, 1), NewPosition(1, 0)},
{NewPosition(2, 0), NewPosition(2, 0)},
{NewPosition(2, 1), NewPosition(3, 0)},
{NewPosition(0, 2), NewPosition(3, 0)},
}

for i, c := range testCases {
last := c.position.LastDescendant()
require.Equalf(t, c.expectedPos, last, "The first descentant position should match for test case %d", i)
}

}
60 changes: 9 additions & 51 deletions balloon/history/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"github.com/bbva/qed/balloon/history/navigation"
"github.com/bbva/qed/balloon/history/pruning"
"github.com/bbva/qed/balloon/history/visit"
"github.com/bbva/qed/hashing"
"github.com/bbva/qed/log"
)
Expand All @@ -30,7 +29,6 @@ type MembershipProof struct {
auditPath navigation.AuditPath
Index, Version uint64
hasher hashing.Hasher // TODO should we remove this and pass as an argument when verifying?
// TODO should we include the eventDigest?
}

func NewMembershipProof(index, version uint64, auditPath navigation.AuditPath, hasher hashing.Hasher) *MembershipProof {
Expand All @@ -49,29 +47,11 @@ func (p MembershipProof) AuditPath() navigation.AuditPath {
// Verify verifies a membership proof
func (p MembershipProof) Verify(eventDigest []byte, expectedDigest hashing.Digest) (correct bool) {

// visitors
computeHash := visit.NewComputeHashVisitor(p.hasher)
log.Debugf("Verifying membership proof for index %d and version %d", p.Index, p.Version)

// build pruning context
var cacheResolver pruning.CacheResolver
if p.Index == p.Version {
cacheResolver = pruning.NewSingleTargetedCacheResolver(p.Version)
} else {
cacheResolver = pruning.NewDoubleTargetedCacheResolver(p.Index, p.Version)
}
context := pruning.NewPruningContext(
cacheResolver,
p.auditPath,
)

// traverse from root and generate a visitable pruned tree
pruned, err := pruning.NewVerifyPruner(p.Version, eventDigest, context).Prune()
if err != nil {
return false
}

// visit the pruned tree
recomputed := pruned.PostOrder(computeHash)
// build a visitable pruned tree and then visit it to recompute root hash
visitor := pruning.NewComputeHashVisitor(p.hasher, p.auditPath)
recomputed := pruning.PruneToVerify(p.Index, p.Version, eventDigest).Accept(visitor)

return bytes.Equal(recomputed, expectedDigest)
}
Expand All @@ -93,34 +73,12 @@ func NewIncrementalProof(start, end uint64, auditPath navigation.AuditPath, hash

func (p IncrementalProof) Verify(startDigest, endDigest hashing.Digest) (correct bool) {

log.Debugf("Verifying incremental between versions %d and %d", p.StartVersion, p.EndVersion)

// visitors
computeHash := visit.NewComputeHashVisitor(p.hasher)

// build pruning context
startContext := pruning.NewPruningContext(
pruning.NewIncrementalCacheResolver(p.StartVersion, p.EndVersion),
p.AuditPath,
)
endContext := pruning.NewPruningContext(
pruning.NewIncrementalCacheResolver(p.StartVersion, p.EndVersion),
p.AuditPath,
)

// traverse from root and generate a visitable pruned tree
startPruned, err := pruning.NewVerifyPruner(p.StartVersion, startDigest, startContext).Prune()
if err != nil {
return false
}
endPruned, err := pruning.NewVerifyPruner(p.EndVersion, endDigest, endContext).Prune()
if err != nil {
return false
}
log.Debugf("Verifying incremental proof between versions %d and %d", p.StartVersion, p.EndVersion)

// visit the pruned trees
startRecomputed := startPruned.PostOrder(computeHash)
endRecomputed := endPruned.PostOrder(computeHash)
// build two visitable pruned trees and then visit them to recompute root hash
visitor := pruning.NewComputeHashVisitor(p.hasher, p.AuditPath)
startRecomputed := pruning.PruneToVerifyIncrementalStart(p.StartVersion).Accept(visitor)
endRecomputed := pruning.PruneToVerifyIncrementalEnd(p.StartVersion, p.EndVersion).Accept(visitor)

return bytes.Equal(startRecomputed, startDigest) && bytes.Equal(endRecomputed, endDigest)

Expand Down
Loading

0 comments on commit f0effb9

Please sign in to comment.