From fa78fe67898165d1b4a4478554cc425a05b054ab Mon Sep 17 00:00:00 2001 From: Gui Iribarren Date: Mon, 4 Nov 2024 20:21:56 +0100 Subject: [PATCH] dirty proof of non-inclusion --- tree/arbo/circomproofs.go | 2 +- tree/arbo/hash.go | 8 +++++++- tree/arbo/proof.go | 30 +++++++++++++++++++++++++++--- tree/arbo/proof_test.go | 15 ++++++++++++++- tree/arbo/tree.go | 3 +++ 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/tree/arbo/circomproofs.go b/tree/arbo/circomproofs.go index 4afdd02d8..d9c147852 100644 --- a/tree/arbo/circomproofs.go +++ b/tree/arbo/circomproofs.go @@ -106,7 +106,7 @@ func (cvp CircomVerifierProof) CalculateProofNodes(hashFunc HashFunction) ([][]b if err != nil { return nil, err } - return CalculateProofNodes(hashFunc, cvp.Key, cvp.Value, packedSiblings) + return CalculateProofNodes(hashFunc, cvp.Key, cvp.Value, packedSiblings, cvp.OldKey, (cvp.Fnc == 1)) } // CheckProof verifies the given proof. The proof verification depends on the diff --git a/tree/arbo/hash.go b/tree/arbo/hash.go index 650f77f03..a1396e69c 100644 --- a/tree/arbo/hash.go +++ b/tree/arbo/hash.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/iden3/go-iden3-crypto/poseidon" + "go.vocdoni.io/dvote/log" "golang.org/x/crypto/blake2b" "lukechampine.com/blake3" ) @@ -148,5 +149,10 @@ func (HashBlake3) Hash(b ...[]byte) ([]byte, error) { return nil, err } } - return hasher.Sum(nil), nil + for _, input := range b { + log.Warnf("input: %x", input) + } + hash := hasher.Sum(nil) + log.Warnf("hash: %x", hash) + return hash, nil } diff --git a/tree/arbo/proof.go b/tree/arbo/proof.go index 97a5bb62a..11cbd8321 100644 --- a/tree/arbo/proof.go +++ b/tree/arbo/proof.go @@ -174,7 +174,7 @@ func bytesToBitmap(b []byte) []bool { // HashFunction passed as parameter. // Returns nil if the proof is valid, or an error otherwise. func CheckProof(hashFunc HashFunction, k, v, root, packedSiblings []byte) error { - hashes, err := CalculateProofNodes(hashFunc, k, v, packedSiblings) + hashes, err := CalculateProofNodes(hashFunc, k, v, packedSiblings, nil, true) if err != nil { return err } @@ -184,9 +184,18 @@ func CheckProof(hashFunc HashFunction, k, v, root, packedSiblings []byte) error return nil } +func keysAreSiblings(k1, k2 []byte) bool { + path1 := getPath(len(k1)*8, slices.Clone(k1)) + path2 := getPath(len(k2)*8, slices.Clone(k2)) + log.Warnf("path1: %+v", path1) + log.Warnf("path2: %+v", path2) + return true +} + // CalculateProofNodes calculates the chain of hashes in the path of the given proof. // In the returned list, first item is the root, and last item is the hash of the leaf. -func CalculateProofNodes(hashFunc HashFunction, k, v, packedSiblings []byte) ([][]byte, error) { +func CalculateProofNodes(hashFunc HashFunction, k, v, packedSiblings, oldKey []byte, exclusion bool) ([][]byte, error) { + log.Warnf("CalculateProofNodes for %x=%x", k, v) siblings, err := UnpackSiblings(hashFunc, packedSiblings) if err != nil { return nil, err @@ -194,6 +203,17 @@ func CalculateProofNodes(hashFunc HashFunction, k, v, packedSiblings []byte) ([] keyPath := make([]byte, int(math.Ceil(float64(len(siblings))/float64(8)))) copy(keyPath, k) + path := getPath(len(siblings), keyPath) + log.Warnf("path (key): %+v", path) + + if exclusion { + if !keysAreSiblings(k, oldKey) { + return nil, fmt.Errorf("exclusion proof invalid, key and oldKey are not siblings") + } + + // we'll prove the path to the existing key (passed as oldKey) + copy(k, oldKey) + } key, _, err := newLeafValue(hashFunc, k, v) if err != nil { @@ -202,7 +222,6 @@ func CalculateProofNodes(hashFunc HashFunction, k, v, packedSiblings []byte) ([] hashes := [][]byte{key} - path := getPath(len(siblings), keyPath) for i, sibling := range slices.Backward(siblings) { if path[i] { key, _, err = newIntermediate(hashFunc, sibling, key) @@ -215,6 +234,9 @@ func CalculateProofNodes(hashFunc HashFunction, k, v, packedSiblings []byte) ([] hashes = append(hashes, key) } slices.Reverse(hashes) + for i, h := range hashes { + log.Warnf("CalculateProofNodes returning %d: %x", i, h) + } return hashes, nil } @@ -230,11 +252,13 @@ func CheckProofBatch(hashFunc HashFunction, oldProofs, newProofs []*CircomVerifi } for i := range oldProofs { + log.Warnf("checking old %x (oldKey %x) (exclusion=%d)", oldProofs[i].Key, oldProofs[i].OldKey, oldProofs[i].Fnc) // Check all old proofs are valid if err := oldProofs[i].CheckProof(hashFunc); err != nil { return fmt.Errorf("old proof invalid: %w", err) } + log.Warnf("checking new %x (exclusion=%d)", newProofs[i].Key, newProofs[i].Fnc) // Map all new branches nodes, err := newProofs[i].CalculateProofNodes(hashFunc) if err != nil { diff --git a/tree/arbo/proof_test.go b/tree/arbo/proof_test.go index bd80073c0..ff93f589d 100644 --- a/tree/arbo/proof_test.go +++ b/tree/arbo/proof_test.go @@ -36,14 +36,27 @@ func TestCheckProofBatch(t *testing.T) { err = tree.Add(BigIntToBytesLE(keyLen, big.NewInt(0x02)), ballotMode) c.Assert(err, qt.IsNil) + err = tree.Add(BigIntToBytesLE(keyLen, big.NewInt(0x03)), ballotMode) + c.Assert(err, qt.IsNil) + var oldProofs, newProofs []*CircomVerifierProof - for i := int64(0x00); i <= int64(0x03); i++ { + for i := int64(0x00); i <= int64(0x10); i++ { proof, err := tree.GenerateCircomVerifierProof(BigIntToBytesLE(keyLen, big.NewInt(i))) c.Assert(err, qt.IsNil) + if i == int64(0x05) { + proof.Key[0] = byte(0x0d) + } oldProofs = append(oldProofs, proof) } + //// HACK to develop non-inclusion proof check + + err = CheckProofBatch(HashFunctionBlake3, oldProofs, oldProofs) + c.Assert(err, qt.IsNil) + panic("blah") + //// HACK + censusRoot[0] = byte(0x02) ballotMode[0] = byte(0x02) diff --git a/tree/arbo/tree.go b/tree/arbo/tree.go index a5a531f3a..e83f5df89 100644 --- a/tree/arbo/tree.go +++ b/tree/arbo/tree.go @@ -20,6 +20,7 @@ import ( "sync" "go.vocdoni.io/dvote/db" + "go.vocdoni.io/dvote/log" ) const ( @@ -150,6 +151,8 @@ func NewTreeWithTx(wTx db.WriteTx, cfg Config) (*Tree, error) { t.emptyHash = make([]byte, t.hashFunction.Len()) // empty var err error t.emptyNode, _, err = t.newIntermediate(t.emptyHash, t.emptyHash) + log.Warnf("emptyHash %x", t.emptyHash) + log.Warnf("emptyNode %x", t.emptyNode) if err != nil { return nil, err }