diff --git a/common/utils.go b/common/utils.go index e0fc78f..bcffa5d 100644 --- a/common/utils.go +++ b/common/utils.go @@ -1,12 +1,14 @@ package common import ( + "bytes" "encoding/hex" "math/big" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/tracerr" "github.com/iden3/go-iden3-crypto/babyjub" + "github.com/iden3/go-merkletree" ) // SwapEndianness swaps the order of the bytes in the slice. @@ -42,3 +44,21 @@ func BJJFromStringWithChecksum(s string) (babyjub.PublicKeyComp, error) { func CopyBigInt(a *big.Int) *big.Int { return new(big.Int).SetBytes(a.Bytes()) } + +// RmEndingZeroes is used to convert the Siblings from a CircomProof into +// Siblings of a merkletree Proof compatible with the js version. This method +// should be used only if it exist an already generated CircomProof compatible +// with circom circuits and a CircomProof compatible with SmartContracts is +// needed. If the proof is not generated yet, this method should not be needed +// and should be used mt.GenerateSCVerifierProof to directly generate the +// CircomProof for the SmartContracts. +func RmEndingZeroes(siblings []*merkletree.Hash) []*merkletree.Hash { + pos := 0 + for i := len(siblings) - 1; i >= 0; i-- { + if !bytes.Equal(siblings[i].Bytes(), merkletree.HashZero.Bytes()) { + pos = i + 1 + break + } + } + return siblings[:pos] +} diff --git a/common/utils_test.go b/common/utils_test.go index 956cb3b..0542ce3 100644 --- a/common/utils_test.go +++ b/common/utils_test.go @@ -4,7 +4,9 @@ import ( "encoding/hex" "testing" + "github.com/iden3/go-merkletree" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestBJJFromStringWithChecksum(t *testing.T) { @@ -22,3 +24,52 @@ func TestBJJFromStringWithChecksum(t *testing.T) { assert.Equal(t, "2492816973395423007340226948038371729989170225696553239457870892535792679622", pk.X.String()) assert.Equal(t, "15238403086306505038849621710779816852318505119327426213168494964113886299863", pk.Y.String()) } + +func TestRmEndingZeroes(t *testing.T) { + s0, err := merkletree.NewHashFromHex("0x0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + s1, err := merkletree.NewHashFromHex("0x0000000000000000000000000000000000000000000000000000000000000001") + require.NoError(t, err) + s2, err := merkletree.NewHashFromHex("0x0000000000000000000000000000000000000000000000000000000000000002") + require.NoError(t, err) + + // expect cropped last zeroes + circomSiblings := []*merkletree.Hash{s0, s1, s0, s1, s1, s1, s2, s0, s0, s0, s0} + siblings := RmEndingZeroes(circomSiblings) + expected := []*merkletree.Hash{s0, s1, s0, s1, s1, s1, s2} + assert.Equal(t, expected, siblings) + + // expect empty array when input is an empty array + siblings = RmEndingZeroes([]*merkletree.Hash{}) + assert.Equal(t, []*merkletree.Hash{}, siblings) + // expect nil when input is nil + siblings = RmEndingZeroes(nil) + assert.Nil(t, siblings) + + // cases when inputs are [x], [x,0], [0,x] + circomSiblings = []*merkletree.Hash{s1} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{s1}, siblings) + circomSiblings = []*merkletree.Hash{s1, s0} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{s1}, siblings) + circomSiblings = []*merkletree.Hash{s0, s1} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{s0, s1}, siblings) + + // expect empty array when input is all zeroes + circomSiblings = []*merkletree.Hash{s0} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{}, siblings) + circomSiblings = []*merkletree.Hash{s0, s0} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{}, siblings) + circomSiblings = []*merkletree.Hash{s0, s0, s0, s0, s0} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, []*merkletree.Hash{}, siblings) + + // expect input equal to output when last element!=0 + circomSiblings = []*merkletree.Hash{s0, s1, s0, s1, s1, s1, s2, s0, s0, s0, s0, s2} + siblings = RmEndingZeroes(circomSiblings) + assert.Equal(t, circomSiblings, siblings) +} diff --git a/db/statedb/statedb.go b/db/statedb/statedb.go index c0e4c5a..457d169 100644 --- a/db/statedb/statedb.go +++ b/db/statedb/statedb.go @@ -328,7 +328,11 @@ func (s *StateDB) MTGetProof(idx common.Idx) (*merkletree.CircomVerifierProof, e if s.MT == nil { return nil, tracerr.Wrap(ErrStateDBWithoutMT) } - return s.MT.GenerateCircomVerifierProof(idx.BigInt(), s.MT.Root()) + p, err := s.MT.GenerateSCVerifierProof(idx.BigInt(), s.MT.Root()) + if err != nil { + return nil, tracerr.Wrap(err) + } + return p, nil } // MTGetRoot returns the current root of the underlying Merkle Tree diff --git a/go.mod b/go.mod index 7a12985..cf77a1a 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/gobuffalo/packr/v2 v2.8.1 github.com/hermeznetwork/tracerr v0.3.1-0.20201126162137-de9930d0cf29 github.com/iden3/go-iden3-crypto v0.0.6-0.20201221160344-58e589b6eb4c - github.com/iden3/go-merkletree v0.0.0-20201218120219-8f3905f15f89 + github.com/iden3/go-merkletree v0.0.0-20201230093451-4280a9914f51 github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee github.com/joho/godotenv v1.3.0 diff --git a/go.sum b/go.sum index 8a5e592..caa0339 100644 --- a/go.sum +++ b/go.sum @@ -309,8 +309,8 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/iden3/go-iden3-crypto v0.0.6-0.20201218111145-a2015adb2f1b/go.mod h1:oBgthFLboAWi9feaBUFy7OxEcyn9vA1khHSL/WwWFyg= github.com/iden3/go-iden3-crypto v0.0.6-0.20201221160344-58e589b6eb4c h1:D2u8FFYey6iFXLsqqJZ8R7ch8gZum+/b98whvoSDbyg= github.com/iden3/go-iden3-crypto v0.0.6-0.20201221160344-58e589b6eb4c/go.mod h1:oBgthFLboAWi9feaBUFy7OxEcyn9vA1khHSL/WwWFyg= -github.com/iden3/go-merkletree v0.0.0-20201218120219-8f3905f15f89 h1:t7tnOTCtw12Rniyk98Hi4gOp0h5JPdzbNcLWCFNj98o= -github.com/iden3/go-merkletree v0.0.0-20201218120219-8f3905f15f89/go.mod h1:MCXbnyoFRwt+7aYHtzVSB3sZZcHLjDf7VZZ2Zqrhqrc= +github.com/iden3/go-merkletree v0.0.0-20201230093451-4280a9914f51 h1:EqkLnC+JlOdX3hQnjq0u2JKcMMmmaQcpmG1udG6BTXw= +github.com/iden3/go-merkletree v0.0.0-20201230093451-4280a9914f51/go.mod h1:MCXbnyoFRwt+7aYHtzVSB3sZZcHLjDf7VZZ2Zqrhqrc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= diff --git a/txprocessor/txprocessor.go b/txprocessor/txprocessor.go index cb3afeb..825f1fd 100644 --- a/txprocessor/txprocessor.go +++ b/txprocessor/txprocessor.go @@ -372,10 +372,11 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat exitAccount := exits[i].acc // 0. generate MerkleProof - p, err := exitTree.GenerateCircomVerifierProof(exitIdx.BigInt(), nil) + p, err := exitTree.GenerateSCVerifierProof(exitIdx.BigInt(), nil) if err != nil { return nil, tracerr.Wrap(err) } + // 1. generate common.ExitInfo ei := common.ExitInfo{ AccountIdx: exitIdx,