Skip to content

Commit

Permalink
GetProofItems is now able to resolve HashedNodes
Browse files Browse the repository at this point in the history
  • Loading branch information
gballet committed Jul 11, 2023
1 parent 2e06387 commit 89d284b
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 43 deletions.
2 changes: 1 addition & 1 deletion empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (Empty) Commitment() *Point {
return &id
}

func (Empty) GetProofItems(keylist) (*ProofElements, []byte, [][]byte, error) {
func (Empty) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
return nil, nil, nil, errors.New("trying to produce a commitment for an empty subtree")
}

Expand Down
2 changes: 1 addition & 1 deletion empty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestEmptyFuncs(t *testing.T) {
t.Fatal("commitment and commit mismatch")
}

if _, _, _, err := e.GetProofItems(nil); err == nil {
if _, _, _, err := e.GetProofItems(nil, nil); err == nil {
t.Fatal("get proof items should error")
}

Expand Down
2 changes: 1 addition & 1 deletion hashednode.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (HashedNode) Commitment() *Point {
panic("can not get commitment of a hash node")
}

func (HashedNode) GetProofItems(keylist) (*ProofElements, []byte, [][]byte, error) {
func (HashedNode) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
return nil, nil, nil, errors.New("can not get the full path, and there is no proof of absence")
}

Expand Down
2 changes: 1 addition & 1 deletion hashednode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestHashedNodeFuncs(t *testing.T) {
if v != nil {
t.Fatal("non-nil get from a hashed node")
}
if _, _, _, err := e.GetProofItems(nil); err == nil {
if _, _, _, err := e.GetProofItems(nil, nil); err == nil {
t.Fatal("got nil error when getting proof items from a hashed node")
}
if _, err := e.Serialize(); err != errSerializeHashedNode {
Expand Down
8 changes: 4 additions & 4 deletions proof_ipa.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ type StemStateDiff struct {

type StateDiff []StemStateDiff

func GetCommitmentsForMultiproof(root VerkleNode, keys [][]byte) (*ProofElements, []byte, [][]byte, error) {
func GetCommitmentsForMultiproof(root VerkleNode, keys [][]byte, resolver NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
sort.Sort(keylist(keys))
return root.GetProofItems(keylist(keys))
return root.GetProofItems(keylist(keys), resolver)
}

func MakeVerkleMultiProof(root VerkleNode, keys [][]byte) (*Proof, []*Point, []byte, []*Fr, error) {
func MakeVerkleMultiProof(root VerkleNode, keys [][]byte, resolver NodeResolverFn) (*Proof, []*Point, []byte, []*Fr, error) {
// go-ipa won't accept no key as an input, catch this corner case
// and return an empty result.
if len(keys) == 0 {
Expand All @@ -89,7 +89,7 @@ func MakeVerkleMultiProof(root VerkleNode, keys [][]byte) (*Proof, []*Point, []b
tr := common.NewTranscript("vt")
root.Commit()

pe, es, poas, err := GetCommitmentsForMultiproof(root, keys)
pe, es, poas, err := GetCommitmentsForMultiproof(root, keys, resolver)
if err != nil {
return nil, nil, nil, nil, err
}
Expand Down
48 changes: 24 additions & 24 deletions proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestProofVerifyTwoLeaves(t *testing.T) {
root.Insert(ffx32KeyTest, zeroKeyTest, nil)
root.Commit()

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ffx32KeyTest})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ffx32KeyTest}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -61,7 +61,7 @@ func TestProofVerifyMultipleLeaves(t *testing.T) {
root.Insert(key, fourtyKeyTest, nil)
}

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{keys[0]})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{keys[0]}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -81,9 +81,9 @@ func TestMultiProofVerifyMultipleLeaves(t *testing.T) {
root.Insert(key, fourtyKeyTest, nil)
}

proof, _, _, _, _ := MakeVerkleMultiProof(root, keys[0:2])
proof, _, _, _, _ := MakeVerkleMultiProof(root, keys[0:2], nil)

pe, _, _, err := GetCommitmentsForMultiproof(root, keys[0:2])
pe, _, _, err := GetCommitmentsForMultiproof(root, keys[0:2], nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -115,9 +115,9 @@ func TestMultiProofVerifyMultipleLeavesWithAbsentStem(t *testing.T) {
absent[3] = 1 // and the stem differs
keys = append(keys, absent)

proof, _, _, _, _ := MakeVerkleMultiProof(root, keys)
proof, _, _, _, _ := MakeVerkleMultiProof(root, keys, nil)

pe, _, isabsent, err := GetCommitmentsForMultiproof(root, keys)
pe, _, isabsent, err := GetCommitmentsForMultiproof(root, keys, nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -142,9 +142,9 @@ func TestMultiProofVerifyMultipleLeavesCommitmentRedundancy(t *testing.T) {
keys[1] = oneKeyTest
root.Insert(keys[1], fourtyKeyTest, nil)

proof, _, _, _, _ := MakeVerkleMultiProof(root, keys)
proof, _, _, _, _ := MakeVerkleMultiProof(root, keys, nil)

pe, _, _, err := GetCommitmentsForMultiproof(root, keys)
pe, _, _, err := GetCommitmentsForMultiproof(root, keys, nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -159,7 +159,7 @@ func TestProofOfAbsenceInternalVerify(t *testing.T) {
root.Insert(zeroKeyTest, zeroKeyTest, nil)
root.Insert(oneKeyTest, zeroKeyTest, nil)

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ffx32KeyTest})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ffx32KeyTest}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -172,7 +172,7 @@ func TestProofOfAbsenceLeafVerify(t *testing.T) {
root.Insert(zeroKeyTest, zeroKeyTest, nil)
root.Insert(ffx32KeyTest, zeroKeyTest, nil)

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{oneKeyTest})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{oneKeyTest}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -189,7 +189,7 @@ func TestProofOfAbsenceLeafVerifyOtherSuffix(t *testing.T) {
return ret
}()

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{key})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{key}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -206,7 +206,7 @@ func TestProofOfAbsenceStemVerify(t *testing.T) {
return ret
}()

proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{key})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{key}, nil)

cfg := GetConfig()
if !VerifyVerkleProof(proof, cis, zis, yis, cfg) {
Expand All @@ -228,7 +228,7 @@ func BenchmarkProofCalculation(b *testing.B) {
b.ReportAllocs()

for i := 0; i < b.N; i++ {
MakeVerkleMultiProof(root, [][]byte{keys[len(keys)/2]})
MakeVerkleMultiProof(root, [][]byte{keys[len(keys)/2]}, nil)
}
}

Expand All @@ -243,7 +243,7 @@ func BenchmarkProofVerification(b *testing.B) {
}

root.Commit()
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{keys[len(keys)/2]})
proof, cis, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{keys[len(keys)/2]}, nil)

b.ResetTimer()
b.ReportAllocs()
Expand All @@ -266,7 +266,7 @@ func TestProofSerializationNoAbsentStem(t *testing.T) {
root.Insert(key, fourtyKeyTest, nil)
}

proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{keys[0]})
proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{keys[0]}, nil)

vp, statediff, err := SerializeProof(proof)
if err != nil {
Expand Down Expand Up @@ -300,7 +300,7 @@ func TestProofSerializationWithAbsentStem(t *testing.T) {
absentkey[2] = 2
absentkey[3] = 1

proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{absentkey[:]})
proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{absentkey[:]}, nil)

vp, statediff, err := SerializeProof(proof)
if err != nil {
Expand Down Expand Up @@ -336,7 +336,7 @@ func TestProofDeserialize(t *testing.T) {
absentkey[2] = 2
absentkey[3] = 1

proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{absentkey[:]})
proof, _, _, _, _ := MakeVerkleMultiProof(root, [][]byte{absentkey[:]}, nil)

vp, statediff, err := SerializeProof(proof)
if err != nil {
Expand All @@ -349,7 +349,7 @@ func TestProofDeserialize(t *testing.T) {
}
_ = deserialized

pe, _, _, err := root.GetProofItems(keylist{absentkey[:]})
pe, _, _, err := root.GetProofItems(keylist{absentkey[:]}, nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -364,7 +364,7 @@ func TestProofOfAbsenceEdgeCase(t *testing.T) {
root.Commit()

ret, _ := hex.DecodeString("0303030303030303030303030303030303030303030303030303030303030303")
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret})
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret}, nil)
cfg := GetConfig()
if !VerifyVerkleProof(proof, cs, zis, yis, cfg) {
t.Fatal("could not verify proof")
Expand All @@ -381,7 +381,7 @@ func TestProofOfAbsenceOtherMultipleLeaves(t *testing.T) {

ret1, _ := hex.DecodeString("0303030303030303030303030303030303030303030303030303030303030300")
ret2, _ := hex.DecodeString("0303030303030303030303030303030303030303030303030303030303030301")
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret1, ret2})
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret1, ret2}, nil)
cfg := GetConfig()
if !VerifyVerkleProof(proof, cs, zis, yis, cfg) {
t.Fatal("could not verify proof")
Expand All @@ -400,7 +400,7 @@ func TestProofOfAbsenceNoneMultipleStems(t *testing.T) {

ret1, _ := hex.DecodeString("0303030303030303030303030303030303030303030303030303030303030300")
ret2, _ := hex.DecodeString("0303030303030303030303030303030303030303030303030303030303030200")
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret1, ret2})
proof, cs, zis, yis, _ := MakeVerkleMultiProof(root, [][]byte{ret1, ret2}, nil)
cfg := GetConfig()
if !VerifyVerkleProof(proof, cs, zis, yis, cfg) {
t.Fatal("could not verify proof")
Expand Down Expand Up @@ -569,7 +569,7 @@ func TestStatelessDeserialize(t *testing.T) {
root.Insert(k, fourtyKeyTest, nil)
}

proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, fourtyKeyTest})
proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, fourtyKeyTest}, nil)

serialized, statediff, err := SerializeProof(proof)
if err != nil {
Expand Down Expand Up @@ -606,7 +606,7 @@ func TestStatelessDeserializeMissingChildNode(t *testing.T) {
root.Insert(k, fourtyKeyTest, nil)
}

proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, fourtyKeyTest})
proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, fourtyKeyTest}, nil)

serialized, statediff, err := SerializeProof(proof)
if err != nil {
Expand Down Expand Up @@ -642,7 +642,7 @@ func TestStatelessDeserializeDepth2(t *testing.T) {
root.Insert(k, fourtyKeyTest, nil)
}

proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, key1})
proof, _, _, _, _ := MakeVerkleMultiProof(root, keylist{zeroKeyTest, key1}, nil)

serialized, statediff, err := SerializeProof(proof)
if err != nil {
Expand Down
23 changes: 18 additions & 5 deletions tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type VerkleNode interface {
// returns them breadth-first. On top of that, it returns
// one "extension status" per stem, and an alternate stem
// if the key is missing but another stem has been found.
GetProofItems(keylist) (*ProofElements, []byte, [][]byte, error)
GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, [][]byte, error)

// Serialize encodes the node to RLP.
Serialize() ([]byte, error)
Expand Down Expand Up @@ -772,7 +772,7 @@ func groupKeys(keys keylist, depth byte) []keylist {
return groups
}

func (n *InternalNode) GetProofItems(keys keylist) (*ProofElements, []byte, [][]byte, error) {
func (n *InternalNode) GetProofItems(keys keylist, resolver NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
var (
groups = groupKeys(keys, n.depth)
pe = &ProofElements{
Expand All @@ -794,7 +794,20 @@ func (n *InternalNode) GetProofItems(keys keylist) (*ProofElements, []byte, [][]
for i, child := range n.children {
fiPtrs[i] = &fi[i]
if child != nil {
points[i] = child.Commitment()
var c VerkleNode
if _, ok := child.(HashedNode); ok {
serialized, err := resolver(keys[0][:n.depth+1])
if err != nil {
return nil, nil, nil, err
}
c, err = ParseNode(serialized, n.depth+1)
if err != nil {
return nil, nil, nil, err
}
} else {
c = child
}
points[i] = c.Commitment()
} else {
// TODO: add a test case to cover this scenario.
points[i] = new(Point)
Expand Down Expand Up @@ -841,7 +854,7 @@ func (n *InternalNode) GetProofItems(keys keylist) (*ProofElements, []byte, [][]
continue
}

pec, es, other, err := n.children[childIdx].GetProofItems(group)
pec, es, other, err := n.children[childIdx].GetProofItems(group, resolver)
if err != nil {
// TODO: add a test case to cover this scenario.
return nil, nil, nil, err
Expand Down Expand Up @@ -1278,7 +1291,7 @@ func leafToComms(poly []Fr, val []byte) error {
return nil
}

func (n *LeafNode) GetProofItems(keys keylist) (*ProofElements, []byte, [][]byte, error) {
func (n *LeafNode) GetProofItems(keys keylist, resolver NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
var (
poly [NodeWidth]Fr // top-level polynomial
pe = &ProofElements{
Expand Down
8 changes: 4 additions & 4 deletions tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ func TestEmptyCommitment(t *testing.T) {
root := New()
root.Insert(zeroKeyTest, zeroKeyTest, nil)
root.Commit()
pe, _, _, err := root.GetProofItems(keylist{ffx32KeyTest})
pe, _, _, err := root.GetProofItems(keylist{ffx32KeyTest}, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -897,7 +897,7 @@ func TestGetProofItemsNoPoaIfStemPresent(t *testing.T) {
key1, _ := hex.DecodeString("ffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
key2, _ := hex.DecodeString("ffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")

_, esses, poas, err := root.GetProofItems(keylist{key1, key2, ffx32KeyTest})
_, esses, poas, err := root.GetProofItems(keylist{key1, key2, ffx32KeyTest}, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1130,7 +1130,7 @@ func TestRustBanderwagonBlock48(t *testing.T) {

r := tree.Commit()

proof, cis, zis, yis, _ := MakeVerkleMultiProof(tree, keys)
proof, cis, zis, yis, _ := MakeVerkleMultiProof(tree, keys, nil)
vp, statediff, err := SerializeProof(proof)
if err != nil {
t.Fatal(err)
Expand All @@ -1151,7 +1151,7 @@ func TestRustBanderwagonBlock48(t *testing.T) {
if err != nil {
t.Fatal(err)
}
pe, _, _, err := droot.GetProofItems(keys)
pe, _, _, err := droot.GetProofItems(keys, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion unknown.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (UnknownNode) Commitment() *Point {
return &id
}

func (UnknownNode) GetProofItems(keylist) (*ProofElements, []byte, [][]byte, error) {
func (UnknownNode) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, [][]byte, error) {
return nil, nil, nil, errors.New("can't generate proof items for unknown node")
}

Expand Down
2 changes: 1 addition & 1 deletion unknown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestUnknownFuncs(t *testing.T) {
if comm := un.Commitment(); !comm.Equal(&identity) {
t.Errorf("got %v, want identity", comm)
}
if _, _, _, err := un.GetProofItems(nil); err == nil {
if _, _, _, err := un.GetProofItems(nil, nil); err == nil {
t.Errorf("got nil error when getting proof items from a hashed node")
}
if _, err := un.Serialize(); err == nil {
Expand Down

0 comments on commit 89d284b

Please sign in to comment.