Skip to content

Commit

Permalink
Merge pull request cosmos#30 from AdityaSripal/aditya/calculate
Browse files Browse the repository at this point in the history
Add Calculate method to CommitmentProof
  • Loading branch information
ethanfrey committed Jun 4, 2020
2 parents 9f53dd0 + 423d657 commit 6e2c36a
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
45 changes: 45 additions & 0 deletions go/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,36 @@ var TendermintSpec = &ProofSpec{
},
}

// Calculate determines the root hash that matches a given Commitment proof
// by type switching and calculating root based on proof type
// NOTE: Calculate will return the first calculated root in the proof,
// you must validate that all other embedded ExistenceProofs commit to the same root.
// This can be done with the Verify method
func (p *CommitmentProof) Calculate() (CommitmentRoot, error) {
switch v := p.Proof.(type) {
case *CommitmentProof_Exist:
return v.Exist.Calculate()
case *CommitmentProof_Nonexist:
return v.Nonexist.Calculate()
case *CommitmentProof_Batch:
if len(v.Batch.GetEntries()) == 0 || v.Batch.GetEntries()[0] == nil {
return nil, errors.New("batch proof has empty entry")
}
if e := v.Batch.GetEntries()[0].GetExist(); e != nil {
return e.Calculate()
}
if n := v.Batch.GetEntries()[0].GetNonexist(); n != nil {
return n.Calculate()
}
case *CommitmentProof_Compressed:
proof := Decompress(p)
return proof.Calculate()
default:
return nil, errors.New("unrecognized proof type")
}
return nil, errors.New("unrecognized proof type")
}

// Verify does all checks to ensure this proof proves this key, value -> root
// and matches the spec.
func (p *ExistenceProof) Verify(spec *ProofSpec, root CommitmentRoot, key []byte, value []byte) error {
Expand Down Expand Up @@ -90,6 +120,21 @@ func (p *ExistenceProof) Calculate() (CommitmentRoot, error) {
return res, nil
}

// Calculate determines the root hash that matches the given nonexistence rpoog.
// You must validate the result is what you have in a header.
// Returns error if the calculations cannot be performed.
func (p *NonExistenceProof) Calculate() (CommitmentRoot, error) {
// A Nonexist proof may have left or right proof nil
switch {
case p.Left != nil:
return p.Left.Calculate()
case p.Right != nil:
return p.Right.Calculate()
default:
return nil, errors.New("Nonexistence proof has empty Left and Right proof")
}
}

// CheckAgainstSpec will verify the leaf and all path steps are in the format defined in spec
func (p *ExistenceProof) CheckAgainstSpec(spec *ProofSpec) error {
if p.GetLeaf() == nil {
Expand Down
11 changes: 11 additions & 0 deletions go/vectors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,19 @@ func TestVectors(t *testing.T) {
}

for _, tc := range cases {
tc := tc
name := fmt.Sprintf("%s/%s", tc.dir, tc.filename)
t.Run(name, func(t *testing.T) {
proof, ref := loadFile(t, tc.dir, tc.filename)
// Test Calculate method
calculatedRoot, err := proof.Calculate()
if err != nil {
t.Fatal("proof.Calculate() returned error")
}
if !bytes.Equal(ref.RootHash, calculatedRoot) {
t.Fatalf("calculated root: %X did not match expected root: %X", calculatedRoot, ref.RootHash)
}
// Test Verify method
if ref.Value == nil {
// non-existence
valid := VerifyNonMembership(tc.spec, ref.RootHash, proof, ref.Key)
Expand Down Expand Up @@ -218,6 +228,7 @@ func TestBatchVectors(t *testing.T) {
}

for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
// try one proof
if tc.ref.Value == nil {
Expand Down

0 comments on commit 6e2c36a

Please sign in to comment.