From 48e4633d1249ed756fe24197c48a6552207be32d Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 30 Dec 2020 10:12:14 +0100 Subject: [PATCH] Add SC proof generator (siblings) --- merkletree.go | 16 +++++++++++++++- merkletree_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/merkletree.go b/merkletree.go index 5f95083..d90a537 100644 --- a/merkletree.go +++ b/merkletree.go @@ -921,6 +921,20 @@ type CircomVerifierProof struct { // key in the MerkleTree. If the rootKey is nil, the current merkletree root // is used. func (mt *MerkleTree) GenerateCircomVerifierProof(k *big.Int, + rootKey *Hash) (*CircomVerifierProof, error) { + cp, err := mt.GenerateSCVerifierProof(k, rootKey) + if err != nil { + return nil, err + } + cp.Siblings = CircomSiblingsFromSiblings(cp.Siblings, mt.maxLevels) + return cp, nil +} + +// GenerateSCVerifierProof returns the CircomVerifierProof for a certain key in +// the MerkleTree with the Siblings without the extra 0 needed at the circom +// circuits, which makes it straight forward to verifiy inside a Smart +// Contract. If the rootKey is nil, the current merkletree root is used. +func (mt *MerkleTree) GenerateSCVerifierProof(k *big.Int, rootKey *Hash) (*CircomVerifierProof, error) { if rootKey == nil { rootKey = mt.Root() @@ -931,7 +945,7 @@ func (mt *MerkleTree) GenerateCircomVerifierProof(k *big.Int, } var cp CircomVerifierProof cp.Root = rootKey - cp.Siblings = CircomSiblingsFromSiblings(p.AllSiblings(), mt.maxLevels) + cp.Siblings = p.AllSiblings() cp.OldKey = &HashZero cp.OldValue = &HashZero cp.Key = NewHashFromBigInt(k) diff --git a/merkletree_test.go b/merkletree_test.go index 6725085..2fa504f 100644 --- a/merkletree_test.go +++ b/merkletree_test.go @@ -706,6 +706,41 @@ func TestUpdateCircomProcessorProof(t *testing.T) { fmt.Sprintf("%v", cpp.Siblings)) } +func TestSmtVerifier(t *testing.T) { + mt, err := NewMerkleTree(memory.NewMemoryStorage(), 4) + assert.Nil(t, err) + + err = mt.Add(big.NewInt(1), big.NewInt(11)) + assert.Nil(t, err) + err = mt.Add(big.NewInt(2), big.NewInt(22)) + assert.Nil(t, err) + err = mt.Add(big.NewInt(3), big.NewInt(33)) + assert.Nil(t, err) + err = mt.Add(big.NewInt(4), big.NewInt(44)) + assert.Nil(t, err) + + cvp, err := mt.GenerateCircomVerifierProof(big.NewInt(2), nil) + assert.Nil(t, err) + + jCvp, err := json.Marshal(cvp) + assert.Nil(t, err) + // Test vectors generated using https://github.com/iden3/circomlib smt.js + // Expect siblings with the extra 0 that the circom circuits need + expected := `{"root":"10171140035965439966839815283432442651152991056297946102647688349369299124493","siblings":["12422661758472400223401299094238820777063458096110016599986781158438915645129","4330149052063565277182642012557086942088176847773467265587998154672740895682","0","0","0"],"oldKey":"0","oldValue":"0","isOld0":false,"key":"2","value":"22","fnc":0}` //nolint:lll + assert.Equal(t, expected, string(jCvp)) + + cvp, err = mt.GenerateSCVerifierProof(big.NewInt(2), nil) + assert.Nil(t, err) + + jCvp, err = json.Marshal(cvp) + assert.Nil(t, err) + // Test vectors generated using https://github.com/iden3/circomlib smt.js + // Without the extra 0 that the circom circuits need, but that are not + // needed at a smart contract verification + expected = `{"root":"10171140035965439966839815283432442651152991056297946102647688349369299124493","siblings":["12422661758472400223401299094238820777063458096110016599986781158438915645129","4330149052063565277182642012557086942088176847773467265587998154672740895682"],"oldKey":"0","oldValue":"0","isOld0":false,"key":"2","value":"22","fnc":0}` //nolint:lll + assert.Equal(t, expected, string(jCvp)) +} + func TestTypesMarshalers(t *testing.T) { // test Hash marshalers h, err := NewHashFromString("42")