From fa7eeeb5d0eb156b65d8c0c242514997916be043 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 3 Nov 2023 10:19:02 -0300 Subject: [PATCH] fix & extra test case Signed-off-by: Ignacio Hagopian --- proof_ipa.go | 10 +++++----- proof_test.go | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/proof_ipa.go b/proof_ipa.go index 775fd0d6..cf1a5b15 100644 --- a/proof_ipa.go +++ b/proof_ipa.go @@ -412,12 +412,12 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // return nil, fmt.Errorf("proof of absence stems are not sorted") } - // We build a cache of stems that have a presence extension status. - stemsWithExtPresent := map[string]struct{}{} + // We build a cache of paths that have a presence extension status. + pathsWithExtPresent := map[string]struct{}{} i := 0 for _, es := range proof.ExtStatus { if es&3 == extStatusPresent { - stemsWithExtPresent[string(stems[i])] = struct{}{} + pathsWithExtPresent[string(stems[i][:es>>3])] = struct{}{} } i++ } @@ -446,14 +446,14 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // // If that is the case, we don't have to do anything since the corresponding leaf will be // constructed by that extension status (already processed or to be processed). // In other case, we should get the stem from the list of proof of absence stems. - if _, ok := stemsWithExtPresent[string(path)]; !ok { + if _, ok := pathsWithExtPresent[string(path)]; !ok { si.stem = poas[0] poas = poas[1:] } // All keys that are part of a proof of absence, must contain empty // prestate values. If that isn't the case, the proof is invalid. for i, k := range proof.Keys { // TODO: DoS risk, use map or binary search. - if bytes.HasPrefix(k, si.stem) { + if bytes.HasPrefix(k, stems[stemIndex]) { if proof.PreValues[i] != nil { return nil, fmt.Errorf("proof of absence (other) stem %x has a value", si.stem) } diff --git a/proof_test.go b/proof_test.go index 1e814eb4..d47bb122 100644 --- a/proof_test.go +++ b/proof_test.go @@ -1016,6 +1016,47 @@ func TestProofOfAbsenceBorderCase(t *testing.T) { } } +func TestProofOfAbsenceBorderCaseReversed(t *testing.T) { + root := New() + + key1, _ := hex.DecodeString("0001000000000000000000000000000000000000000000000000000000000001") + key2, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001") + + // Insert an arbitrary value at key 0000000000000000000000000000000000000000000000000000000000000001 + if err := root.Insert(key1, fourtyKeyTest, nil); err != nil { + t.Fatalf("could not insert key: %v", err) + } + + // Generate a proof for the following keys: + // - key1, which is present. + // - key2, which isn't present. + // Note that all three keys will land on the same leaf value. + proof, _, _, _, _ := MakeVerkleMultiProof(root, nil, keylist{key1, key2}, nil) + + serialized, statediff, err := SerializeProof(proof) + if err != nil { + t.Fatalf("could not serialize proof: %v", err) + } + + dproof, err := DeserializeProof(serialized, statediff) + if err != nil { + t.Fatalf("error deserializing proof: %v", err) + } + + droot, err := PreStateTreeFromProof(dproof, root.Commit()) + if err != nil { + t.Fatal(err) + } + + if !droot.Commit().Equal(root.Commit()) { + t.Fatal("differing root commitments") + } + + if !droot.(*InternalNode).children[0].Commit().Equal(root.(*InternalNode).children[0].Commit()) { + t.Fatal("differing commitment for child #0") + } +} + func TestGenerateProofWithOnlyAbsentKeys(t *testing.T) { t.Parallel() @@ -1141,7 +1182,7 @@ func TestDoubleProofOfAbsence(t *testing.T) { } // Try to prove to different stems that end up in the same LeafNode without any other proof of presence - // in that leaf node. i.e: two proof of absence in the same leaf node with no proof of absence. + // in that leaf node. i.e: two proof of absence in the same leaf node with no proof of presence. key2, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000100") key3, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000200") proof, _, _, _, _ := MakeVerkleMultiProof(root, nil, keylist{key2, key3}, nil)