diff --git a/proof_ipa.go b/proof_ipa.go index 775fd0d6..3054b36f 100644 --- a/proof_ipa.go +++ b/proof_ipa.go @@ -413,11 +413,11 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // } // We build a cache of stems that have a presence extension status. - stemsWithExtPresent := map[string]struct{}{} + 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,7 +446,7 @@ 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:] } 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)