From c1fd0d66269cb9126aac6b0216f5eff0e0290983 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 3 Dec 2020 16:24:15 +0100 Subject: [PATCH] ZKInputs with Fee txs compatible with circom - Separate ZKInputs tests at StateDB package - Small fix at ZKInputs generation FeeIdxs length - Fees related parameters at ZKInputs works properly - Add ZKInputs generation test with fees (`TestZKInputs1`), which output has been tested with circom to ensure compatibility --- common/zk.go | 24 +- db/statedb/txprocessors.go | 17 +- db/statedb/txprocessors_test.go | 331 ------------------------- db/statedb/zkinputsgen_test.go | 424 ++++++++++++++++++++++++++++++++ 4 files changed, 444 insertions(+), 352 deletions(-) create mode 100644 db/statedb/zkinputsgen_test.go diff --git a/common/zk.go b/common/zk.go index 51510d2..5073811 100644 --- a/common/zk.go +++ b/common/zk.go @@ -203,7 +203,8 @@ type ZKInputs struct { // account creation type. ISOutIdx []*big.Int `json:"imOutIdx"` // uint64 (max nLevels bits), len: [nTx - 1] // rollup-tx - // ISStateRoot root at the moment of the Tx (once processed), the state root value once the Tx is processed into the state tree + // ISStateRoot root at the moment of the Tx (once processed), the state + // root value once the Tx is processed into the state tree ISStateRoot []*big.Int `json:"imStateRoot"` // Hash, len: [nTx - 1] // ISExitTree root at the moment (once processed) of the Tx the value // once the Tx is processed into the exit tree @@ -211,10 +212,12 @@ type ZKInputs struct { // ISAccFeeOut accumulated fees once the Tx is processed. Contains the // array of FeeAccount Balances at each moment of each Tx processed. ISAccFeeOut [][]*big.Int `json:"imAccFeeOut"` // big.Int, len: [nTx - 1][maxFeeIdxs] - // fee-tx - // ISStateRootFee root at the moment of the Tx (once processed), the state root value once the Tx is processed into the state tree + // fee-tx: + // ISStateRootFee root at the moment of the Tx (once processed), the + // state root value once the Tx is processed into the state tree ISStateRootFee []*big.Int `json:"imStateRootFee"` // Hash, len: [maxFeeIdxs - 1] - // ISInitStateRootFee state root once all L1-L2 tx are processed (before computing the fees-tx) + // ISInitStateRootFee state root once all L1-L2 tx are processed + // (before computing the fees-tx) ISInitStateRootFee *big.Int `json:"imInitStateRootFee"` // Hash // ISFinalAccFee final accumulated fees (before computing the fees-tx). // Contains the final values of the ISAccFeeOut parameter @@ -283,8 +286,8 @@ func NewZKInputs(nTx, maxL1Tx, maxTx, maxFeeIdxs, nLevels uint32, currentNumBatc zki := &ZKInputs{} zki.Metadata.NTx = nTx zki.Metadata.MaxFeeIdxs = maxFeeIdxs - zki.Metadata.NLevels = nLevels zki.Metadata.MaxLevels = uint32(48) //nolint:gomnd + zki.Metadata.NLevels = nLevels zki.Metadata.MaxL1Tx = maxL1Tx zki.Metadata.MaxTx = maxTx @@ -424,6 +427,7 @@ func (z ZKInputs) HashGlobalData() (*big.Int, error) { func (z ZKInputs) ToHashGlobalData() ([]byte, error) { var b []byte bytesMaxLevels := int(z.Metadata.MaxLevels / 8) //nolint:gomnd + bytesNLevels := int(z.Metadata.NLevels / 8) //nolint:gomnd // [MAX_NLEVELS bits] oldLastIdx oldLastIdx := make([]byte, bytesMaxLevels) @@ -490,16 +494,10 @@ func (z ZKInputs) ToHashGlobalData() ([]byte, error) { // [NLevels * MAX_TOKENS_FEE bits] feeTxsData for i := 0; i < len(z.FeeIdxs); i++ { - var r []byte - - padding := make([]byte, bytesMaxLevels/4) //nolint:gomnd - r = append(r, padding...) - - feeIdx := make([]byte, bytesMaxLevels/2) //nolint:gomnd + feeIdx := make([]byte, bytesNLevels) //nolint:gomnd feeIdxBytes := z.FeeIdxs[i].Bytes() copy(feeIdx[len(feeIdx)-len(feeIdxBytes):], feeIdxBytes[:]) - r = append(r, feeIdx...) - b = append(b, r...) + b = append(b, feeIdx...) } // [16 bits] chainID diff --git a/db/statedb/txprocessors.go b/db/statedb/txprocessors.go index 693a62b..c96e5fd 100644 --- a/db/statedb/txprocessors.go +++ b/db/statedb/txprocessors.go @@ -287,12 +287,6 @@ func (s *StateDB) ProcessTxs(ptc ProcessTxsConfig, coordIdxs []common.Idx, l1use log.Errorw("Can not distribute accumulated fees to coordinator account: No coord Idx to receive fee", "idx", idx) return nil, tracerr.Wrap(err) } - accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee) - pFee, err := s.UpdateAccount(idx, accCoord) - if err != nil { - log.Error(err) - return nil, tracerr.Wrap(err) - } if s.zki != nil { s.zki.TokenID3[iFee] = accCoord.TokenID.BigInt() s.zki.Nonce3[iFee] = accCoord.Nonce.BigInt() @@ -302,11 +296,18 @@ func (s *StateDB) ProcessTxs(ptc ProcessTxsConfig, coordIdxs []common.Idx, l1use s.zki.Ay3[iFee] = accCoord.PublicKey.Y s.zki.Balance3[iFee] = accCoord.Balance s.zki.EthAddr3[iFee] = common.EthAddrToBigInt(accCoord.EthAddr) - s.zki.Siblings3[iFee] = siblingsToZKInputFormat(pFee.Siblings) // add Coord Idx to ZKInputs.FeeTxsData s.zki.FeeIdxs[iFee] = idx.BigInt() - + } + accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee) + pFee, err := s.UpdateAccount(idx, accCoord) + if err != nil { + log.Error(err) + return nil, tracerr.Wrap(err) + } + if s.zki != nil { + s.zki.Siblings3[iFee] = siblingsToZKInputFormat(pFee.Siblings) s.zki.ISStateRootFee[iFee] = s.mt.Root().BigInt() } iFee++ diff --git a/db/statedb/txprocessors_test.go b/db/statedb/txprocessors_test.go index b0d18d5..e8064ec 100644 --- a/db/statedb/txprocessors_test.go +++ b/db/statedb/txprocessors_test.go @@ -1,9 +1,6 @@ package statedb import ( - "encoding/hex" - "encoding/json" - "fmt" "io/ioutil" "math/big" "os" @@ -13,7 +10,6 @@ import ( "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/test/til" - "github.com/iden3/go-iden3-crypto/babyjub" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -481,67 +477,6 @@ func TestProcessTxsBatchBuilder(t *testing.T) { assert.Equal(t, "2", acc.Balance.String()) } -func TestZKInputsGeneration(t *testing.T) { - dir, err := ioutil.TempDir("", "tmpdb") - require.Nil(t, err) - defer assert.Nil(t, os.RemoveAll(dir)) - - sdb, err := NewStateDB(dir, TypeBatchBuilder, 4) - assert.Nil(t, err) - - set := ` - Type: Blockchain - AddToken(1) - CreateAccountDeposit(1) A: 10 - > batchL1 - CreateAccountCoordinator(1) B - CreateAccountCoordinator(1) C - > batchL1 - // idxs: A:258, B:256, C:257 - - Transfer(1) A-B: 6 (1) - Transfer(1) A-C: 2 (1) - > batch - > block - ` - // generate test transactions from test.SetBlockchain0 code - tc := til.NewContext(common.RollupConstMaxL1UserTx) - blocks, err := tc.GenerateBlocks(set) - require.Nil(t, err) - - // Coordinator Idx where to send the fees - coordIdxs := []common.Idx{256} - - ptc := ProcessTxsConfig{ - NLevels: 32, - MaxFeeTx: 8, - MaxTx: 32, - MaxL1Tx: 16, - } - - log.Debug("block:0 batch:0, only L1UserTx") - _, err = sdb.ProcessTxs(ptc, nil, blocks[0].Rollup.L1UserTxs, nil, nil) - require.Nil(t, err) - - log.Debug("block:0 batch:1, only L1CoordinatorTxs") - _, err = sdb.ProcessTxs(ptc, nil, nil, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, nil) - require.Nil(t, err) - - log.Debug("block:0 batch:2, only L2Txs") - l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs) - ptOut, err := sdb.ProcessTxs(ptc, coordIdxs, nil, nil, l2Txs) - require.Nil(t, err) - checkBalance(t, tc, sdb, "A", 1, "2") - - s, err := json.Marshal(ptOut.ZKInputs) - require.Nil(t, err) - debug := false - // debug = true - if debug { - fmt.Println(string(s)) - } -} - func TestProcessTxsRootTestVectors(t *testing.T) { dir, err := ioutil.TempDir("", "tmpdb") require.Nil(t, err) @@ -588,269 +523,3 @@ func TestProcessTxsRootTestVectors(t *testing.T) { require.Nil(t, err) assert.Equal(t, "9827704113668630072730115158977131501210702363656902211840117643154933433410", sdb.mt.Root().BigInt().String()) } - -func TestCircomTest(t *testing.T) { - dir, err := ioutil.TempDir("", "tmpdb") - require.Nil(t, err) - defer assert.Nil(t, os.RemoveAll(dir)) - - nLevels := 16 - - sdb, err := NewStateDB(dir, TypeBatchBuilder, nLevels) - assert.Nil(t, err) - - // same values than in the js test - // skJsHex is equivalent to the 0000...0001 js private key in commonjs - skJsHex := "7eb258e61862aae75c6c1d1f7efae5006ffc9e4d5596a6ff95f3df4ea209ea7f" - skJs, err := hex.DecodeString(skJsHex) - require.Nil(t, err) - var sk0 babyjub.PrivateKey - copy(sk0[:], skJs) - bjj0 := sk0.Public() - assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", bjj0.String()) - - l1Txs := []common.L1Tx{ - { - FromIdx: 0, - DepositAmount: big.NewInt(16000000), - Amount: big.NewInt(0), - TokenID: 1, - FromBJJ: bjj0, - FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), - ToIdx: 0, - Type: common.TxTypeCreateAccountDeposit, - UserOrigin: true, - }, - } - l2Txs := []common.PoolL2Tx{ - { - FromIdx: 256, - ToIdx: 256, - TokenID: 1, - Amount: big.NewInt(1000), - Nonce: 0, - Fee: 0, - Type: common.TxTypeTransfer, - }, - } - - toSign, err := l2Txs[0].HashToSign() - require.Nil(t, err) - sig := sk0.SignPoseidon(toSign) - l2Txs[0].Signature = sig.Compress() - - ptc := ProcessTxsConfig{ - NLevels: uint32(nLevels), - MaxTx: 3, - MaxL1Tx: 2, - MaxFeeTx: 2, - } - // skip first batch to do the test with BatchNum=1 - _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) - require.Nil(t, err) - - ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) - require.Nil(t, err) - - // check expected account keys values from tx inputs - acc, err := sdb.GetAccount(common.Idx(256)) - require.Nil(t, err) - assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) - assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) - - // check that there no exist more accounts - _, err = sdb.GetAccount(common.Idx(257)) - require.NotNil(t, err) - - s, err := json.Marshal(ptOut.ZKInputs) - require.Nil(t, err) - - debug := false - // debug = true - if debug { - fmt.Println("\nCopy&Paste into js circom test:\n let zkInput = JSON.parse(`" + string(s) + "`);") - // fmt.Println("\nZKInputs json:\n echo '" + string(s) + "' | jq") - - h, err := ptOut.ZKInputs.HashGlobalData() - require.Nil(t, err) - fmt.Printf(` - const output={ - hashGlobalInputs: "%s", - }; - await circuit.assertOut(w, output); - `, h.String()) - fmt.Println("") - } - - // the 'expected' data has been checked with the circom circuits - expected := `{"auxFromIdx":["256","0","0"],"auxToIdx":["0","0","0"],"ay1":["15238403086306505038849621710779816852318505119327426213168494964113886299863","15238403086306505038849621710779816852318505119327426213168494964113886299863","0"],"ay2":["0","15238403086306505038849621710779816852318505119327426213168494964113886299863","0"],"ay3":["0","0"],"balance1":["16000000","16000000","0"],"balance2":["0","15999000","0"],"balance3":["0","0"],"currentNumBatch":"1","ethAddr1":["721457446580647751014191829380889690493307935711","721457446580647751014191829380889690493307935711","0"],"ethAddr2":["0","721457446580647751014191829380889690493307935711","0"],"ethAddr3":["0","0"],"feeIdxs":["0","0"],"feePlanTokens":["0","0"],"fromBjjCompressed":[["1","1","1","0","1","0","1","1","0","1","1","0","0","0","1","0","0","1","0","0","0","0","0","1","1","1","1","1","0","0","1","0","1","0","1","1","1","1","1","0","0","1","0","1","0","0","0","0","1","0","1","0","0","0","1","1","0","0","1","0","0","0","0","0","0","1","0","1","0","0","1","0","1","1","1","0","1","0","1","0","1","1","1","1","1","1","0","0","1","0","0","0","1","0","1","0","0","1","0","0","1","1","0","1","0","0","0","1","1","1","1","0","0","0","1","1","0","1","0","1","1","0","1","0","1","1","0","1","1","0","1","1","0","1","1","0","0","1","0","0","0","0","0","1","1","1","0","1","1","1","0","0","0","0","1","1","0","1","1","1","1","0","0","1","1","1","0","0","1","0","1","0","1","0","1","0","1","0","1","1","1","0","0","0","1","0","1","1","1","0","0","0","1","1","0","1","1","1","1","0","1","1","1","0","1","1","1","1","1","1","1","0","1","1","0","0","1","1","0","1","0","0","0","1","0","0","0","1","0","1","1","0","1","0","0","0","0","1","0","1","0","0","0","0","1","1","0","1","1","0","0","0","0","1","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"fromEthAddr":["721457446580647751014191829380889690493307935711","0","0"],"fromIdx":["0","256","0"],"globalChainID":"0","imAccFeeOut":[["0","0"],["0","0"]],"imExitRoot":["0","0"],"imFinalAccFee":["0","0"],"imInitStateRootFee":"3212803832159212591526550848126062808026208063555125878245901046146545013161","imOnChain":["1","0"],"imOutIdx":["256","256"],"imStateRoot":["2999178063326948609414231200730958862089790119006655219527433501846141543551","3212803832159212591526550848126062808026208063555125878245901046146545013161"],"imStateRootFee":["3212803832159212591526550848126062808026208063555125878245901046146545013161"],"isOld0_1":["1","0","0"],"isOld0_2":["0","0","0"],"loadAmountF":["10400","0","0"],"maxNumBatch":["0","0","0"],"newAccount":["1","0","0"],"newExit":["0","0","0"],"nonce1":["0","0","0"],"nonce2":["0","1","0"],"nonce3":["0","0"],"oldKey1":["0","0","0"],"oldKey2":["0","0","0"],"oldLastIdx":"255","oldStateRoot":"0","oldValue1":["0","0","0"],"oldValue2":["0","0","0"],"onChain":["1","0","0"],"r8x":["0","13339118088097183560380359255316479838355724395928453439485234854234470298884","0"],"r8y":["0","12062876403986777372637801733000285846673058725183957648593976028822138986587","0"],"rqOffset":["0","0","0"],"rqToBjjAy":["0","0","0"],"rqToEthAddr":["0","0","0"],"rqTxCompressedDataV2":["0","0","0"],"s":["0","1429292460142966038093363510339656828866419125109324886747095533117015974779","0"],"siblings1":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings2":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings3":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"sign1":["0","0","0"],"sign2":["0","0","0"],"sign3":["0","0"],"toBjjAy":["0","0","0"],"toEthAddr":["0","0","0"],"toIdx":["0","256","0"],"tokenID1":["1","1","0"],"tokenID2":["0","1","0"],"tokenID3":["0","0"],"txCompressedData":["1461501637330902918203684832716283019659255211535","1483802382529433561627630154640673862706524841487","3322668559"],"txCompressedDataV2":["0","5271525021049092038181634317484288","0"]}` - assert.Equal(t, expected, string(s)) -} - -func TestZKInputsHashTestVector0(t *testing.T) { - dir, err := ioutil.TempDir("", "tmpdb") - require.Nil(t, err) - defer assert.Nil(t, os.RemoveAll(dir)) - - sdb, err := NewStateDB(dir, TypeBatchBuilder, 32) - assert.Nil(t, err) - - // same values than in the js test - bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7") - assert.Nil(t, err) - l1Txs := []common.L1Tx{ - { - FromIdx: 0, - DepositAmount: big.NewInt(16000000), - Amount: big.NewInt(0), - TokenID: 1, - FromBJJ: bjj0, - FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), - ToIdx: 0, - Type: common.TxTypeCreateAccountDeposit, - UserOrigin: true, - }, - } - l2Txs := []common.PoolL2Tx{ - { - FromIdx: 256, - ToIdx: 256, - TokenID: 1, - Amount: big.NewInt(1000), - Nonce: 0, - Fee: 126, - Type: common.TxTypeTransfer, - }, - } - - ptc := ProcessTxsConfig{ - NLevels: 32, - MaxFeeTx: 8, - MaxTx: 32, - MaxL1Tx: 16, - } - // skip first batch to do the test with BatchNum=1 - _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) - require.Nil(t, err) - - ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) - require.Nil(t, err) - - // check expected account keys values from tx inputs - acc, err := sdb.GetAccount(common.Idx(256)) - require.Nil(t, err) - assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) - assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) - - // check that there no exist more accounts - _, err = sdb.GetAccount(common.Idx(257)) - require.NotNil(t, err) - ptOut.ZKInputs.FeeIdxs[0] = common.Idx(256).BigInt() - - toHash, err := ptOut.ZKInputs.ToHashGlobalData() - assert.Nil(t, err) - // value from js test vector - expectedToHash := "0000000000ff000000000100000000000000000000000000000000000000000000000000000000000000000015ba488d749f6b891d29d0bf3a72481ec812e4d4ecef2bf7a3fc64f3c010444200000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010003e87e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000001" - // checks are splitted to find the difference easier - assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000]) - assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000]) - assert.Equal(t, expectedToHash[2000:], hex.EncodeToString(toHash)[2000:]) - - h, err := ptOut.ZKInputs.HashGlobalData() - require.Nil(t, err) - // value from js test vector - assert.Equal(t, "4356692423721763303547321618014315464040324829724049399065961225345730555597", h.String()) -} - -func TestZKInputsHashTestVector1(t *testing.T) { - dir, err := ioutil.TempDir("", "tmpdb") - require.Nil(t, err) - defer assert.Nil(t, os.RemoveAll(dir)) - - sdb, err := NewStateDB(dir, TypeBatchBuilder, 32) - assert.Nil(t, err) - - // same values than in the js test - bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7") - assert.Nil(t, err) - bjj1, err := common.BJJFromStringWithChecksum("093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d") - assert.Nil(t, err) - l1Txs := []common.L1Tx{ - { - FromIdx: 0, - // DepositAmount: big.NewInt(10400), - DepositAmount: big.NewInt(16000000), - Amount: big.NewInt(0), - TokenID: 1, - FromBJJ: bjj0, - FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), - ToIdx: 0, - Type: common.TxTypeCreateAccountDeposit, - UserOrigin: true, - }, - { - FromIdx: 0, - DepositAmount: big.NewInt(16000000), - Amount: big.NewInt(0), - TokenID: 1, - FromBJJ: bjj1, - FromEthAddr: ethCommon.HexToAddress("0x2b5ad5c4795c026514f8317c7a215e218dccd6cf"), - ToIdx: 0, - Type: common.TxTypeCreateAccountDeposit, - UserOrigin: true, - }, - } - l2Txs := []common.PoolL2Tx{ - { - FromIdx: 257, - ToIdx: 256, - TokenID: 1, - Amount: big.NewInt(1000), - Nonce: 0, - Fee: 137, - Type: common.TxTypeTransfer, - }, - } - - ptc := ProcessTxsConfig{ - NLevels: 32, - MaxFeeTx: 8, - MaxTx: 32, - MaxL1Tx: 16, - } - // skip first batch to do the test with BatchNum=1 - _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) - require.Nil(t, err) - - ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) - require.Nil(t, err) - - // check expected account keys values from tx inputs - acc, err := sdb.GetAccount(common.Idx(256)) - require.Nil(t, err) - assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) - assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) - acc, err = sdb.GetAccount(common.Idx(257)) - require.Nil(t, err) - assert.Equal(t, "4d05c307400c65795f02db96b1b81c60386fd53e947d9d3f749f3d99b1853909", acc.PublicKey.Compress().String()) - assert.Equal(t, "0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF", acc.EthAddr.Hex()) - - // check that there no exist more accounts - _, err = sdb.GetAccount(common.Idx(258)) - require.NotNil(t, err) - ptOut.ZKInputs.FeeIdxs[0] = common.Idx(257).BigInt() - - toHash, err := ptOut.ZKInputs.ToHashGlobalData() - assert.Nil(t, err) - // value from js test vector - expectedToHash := "0000000000ff0000000001010000000000000000000000000000000000000000000000000000000000000000304a3f3aef4f416cca887aab7265227449077627138345c2eb25bf8ff946b09500000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d00000000000028a000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000010003e889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000000001" - // checks are splitted to find the difference easier - assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000]) - assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000]) - assert.Equal(t, expectedToHash[2000:], hex.EncodeToString(toHash)[2000:]) - - h, err := ptOut.ZKInputs.HashGlobalData() - require.Nil(t, err) - // value from js test vector - assert.Equal(t, "20293112365009290386650039345314592436395562810005523677125576447132206192598", h.String()) -} diff --git a/db/statedb/zkinputsgen_test.go b/db/statedb/zkinputsgen_test.go new file mode 100644 index 0000000..e7a342c --- /dev/null +++ b/db/statedb/zkinputsgen_test.go @@ -0,0 +1,424 @@ +package statedb + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "os" + "testing" + + ethCommon "github.com/ethereum/go-ethereum/common" + "github.com/hermeznetwork/hermez-node/common" + "github.com/iden3/go-iden3-crypto/babyjub" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func printZKInputs(t *testing.T, zki *common.ZKInputs) { + s, err := json.Marshal(zki) + require.Nil(t, err) + h, err := zki.HashGlobalData() + require.Nil(t, err) + + fmt.Println("\nCopy&Paste into js circom test:\n let zkInput = JSON.parse(`" + string(s) + "`);") + // fmt.Println("\nZKInputs json:\n echo '" + string(s) + "' | jq") + + fmt.Printf(` + const output={ + hashGlobalInputs: "%s", + }; + await circuit.assertOut(w, output); + `, h.String()) + fmt.Println("") +} + +func TestZKInputsHashTestVector0(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + defer assert.Nil(t, os.RemoveAll(dir)) + + sdb, err := NewStateDB(dir, TypeBatchBuilder, 32) + assert.Nil(t, err) + + // same values than in the js test + bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7") + assert.Nil(t, err) + l1Txs := []common.L1Tx{ + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj0, + FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + } + l2Txs := []common.PoolL2Tx{ + { + FromIdx: 256, + ToIdx: 256, + TokenID: 1, + Amount: big.NewInt(1000), + Nonce: 0, + Fee: 126, + Type: common.TxTypeTransfer, + }, + } + + ptc := ProcessTxsConfig{ + NLevels: 32, + MaxFeeTx: 8, + MaxTx: 32, + MaxL1Tx: 16, + } + // skip first batch to do the test with BatchNum=1 + _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) + require.Nil(t, err) + + ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) + require.Nil(t, err) + + // check expected account keys values from tx inputs + acc, err := sdb.GetAccount(common.Idx(256)) + require.Nil(t, err) + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) + + // check that there no exist more accounts + _, err = sdb.GetAccount(common.Idx(257)) + require.NotNil(t, err) + ptOut.ZKInputs.FeeIdxs[0] = common.Idx(256).BigInt() + + toHash, err := ptOut.ZKInputs.ToHashGlobalData() + assert.Nil(t, err) + // value from js test vector + expectedToHash := "0000000000ff000000000100000000000000000000000000000000000000000000000000000000000000000015ba488d749f6b891d29d0bf3a72481ec812e4d4ecef2bf7a3fc64f3c010444200000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010003e87e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000001" + // checks are splitted to find the difference easier + assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000]) + assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000]) + assert.Equal(t, expectedToHash[2000:], hex.EncodeToString(toHash)[2000:]) + + h, err := ptOut.ZKInputs.HashGlobalData() + require.Nil(t, err) + // value from js test vector + assert.Equal(t, "4356692423721763303547321618014315464040324829724049399065961225345730555597", h.String()) +} + +func TestZKInputsHashTestVector1(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + defer assert.Nil(t, os.RemoveAll(dir)) + + sdb, err := NewStateDB(dir, TypeBatchBuilder, 32) + assert.Nil(t, err) + + // same values than in the js test + bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7") + assert.Nil(t, err) + bjj1, err := common.BJJFromStringWithChecksum("093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d") + assert.Nil(t, err) + l1Txs := []common.L1Tx{ + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj0, + FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj1, + FromEthAddr: ethCommon.HexToAddress("0x2b5ad5c4795c026514f8317c7a215e218dccd6cf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + } + l2Txs := []common.PoolL2Tx{ + { + FromIdx: 257, + ToIdx: 256, + TokenID: 1, + Amount: big.NewInt(1000), + Nonce: 0, + Fee: 137, + Type: common.TxTypeTransfer, + }, + } + + ptc := ProcessTxsConfig{ + NLevels: 32, + MaxFeeTx: 8, + MaxTx: 32, + MaxL1Tx: 16, + } + // skip first batch to do the test with BatchNum=1 + _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) + require.Nil(t, err) + + ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) + require.Nil(t, err) + + // check expected account keys values from tx inputs + acc, err := sdb.GetAccount(common.Idx(256)) + require.Nil(t, err) + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) + acc, err = sdb.GetAccount(common.Idx(257)) + require.Nil(t, err) + assert.Equal(t, "4d05c307400c65795f02db96b1b81c60386fd53e947d9d3f749f3d99b1853909", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF", acc.EthAddr.Hex()) + + // check that there no exist more accounts + _, err = sdb.GetAccount(common.Idx(258)) + require.NotNil(t, err) + ptOut.ZKInputs.FeeIdxs[0] = common.Idx(257).BigInt() + + toHash, err := ptOut.ZKInputs.ToHashGlobalData() + assert.Nil(t, err) + // value from js test vector + expectedToHash := "0000000000ff0000000001010000000000000000000000000000000000000000000000000000000000000000304a3f3aef4f416cca887aab7265227449077627138345c2eb25bf8ff946b09500000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d00000000000028a000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000010003e889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000000001" + // checks are splitted to find the difference easier + assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000]) + assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000]) + assert.Equal(t, expectedToHash[2000:], hex.EncodeToString(toHash)[2000:]) + + h, err := ptOut.ZKInputs.HashGlobalData() + require.Nil(t, err) + // value from js test vector + assert.Equal(t, "20293112365009290386650039345314592436395562810005523677125576447132206192598", h.String()) +} + +// TestZKInputs0: +// - 1 L1Tx +// - 1 L2Tx without fees +// no Coordinator Idxs defined to receive the fees +func TestZKInputs0(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + defer assert.Nil(t, os.RemoveAll(dir)) + + nLevels := 16 + + sdb, err := NewStateDB(dir, TypeBatchBuilder, nLevels) + assert.Nil(t, err) + + // same values than in the js test + // skJsHex is equivalent to the 0000...0001 js private key in commonjs + skJsHex := "7eb258e61862aae75c6c1d1f7efae5006ffc9e4d5596a6ff95f3df4ea209ea7f" + skJs, err := hex.DecodeString(skJsHex) + require.Nil(t, err) + var sk0 babyjub.PrivateKey + copy(sk0[:], skJs) + bjj0 := sk0.Public() + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", bjj0.String()) + + l1Txs := []common.L1Tx{ + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj0, + FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + } + l2Txs := []common.PoolL2Tx{ + { + FromIdx: 256, + ToIdx: 256, + TokenID: 1, + Amount: big.NewInt(1000), + Nonce: 0, + Fee: 0, + Type: common.TxTypeTransfer, + }, + } + + toSign, err := l2Txs[0].HashToSign() + require.Nil(t, err) + sig := sk0.SignPoseidon(toSign) + l2Txs[0].Signature = sig.Compress() + + ptc := ProcessTxsConfig{ + NLevels: uint32(nLevels), + MaxTx: 3, + MaxL1Tx: 2, + MaxFeeTx: 2, + } + // skip first batch to do the test with BatchNum=1 + _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) + require.Nil(t, err) + + ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs) + require.Nil(t, err) + + // check expected account keys values from tx inputs + acc, err := sdb.GetAccount(common.Idx(256)) + require.Nil(t, err) + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) + + // check that there no exist more accounts + _, err = sdb.GetAccount(common.Idx(257)) + require.NotNil(t, err) + + debug := false + // debug = true + if debug { + printZKInputs(t, ptOut.ZKInputs) + } + toHash, err := ptOut.ZKInputs.ToHashGlobalData() + require.Nil(t, err) + assert.Equal(t, "0000000000ff0000000001000000000000000000000000000000000000000000000000000000000000000000071a61ed5a1ac052b0d1086a330c540b55318a07f6b7989573b9bbbb5380d1a900000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a0000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010003e8000000000000000000000000000000000001", hex.EncodeToString(toHash)) + + h, err := ptOut.ZKInputs.HashGlobalData() + require.Nil(t, err) + assert.Equal(t, "10273997725311869157325593477103834352520120955255334791164183491223442653056", h.String()) + + s, err := json.Marshal(ptOut.ZKInputs) + require.Nil(t, err) + + // the 'expected' data has been checked with the circom circuits + expected := `{"auxFromIdx":["256","0","0"],"auxToIdx":["0","0","0"],"ay1":["15238403086306505038849621710779816852318505119327426213168494964113886299863","15238403086306505038849621710779816852318505119327426213168494964113886299863","0"],"ay2":["0","15238403086306505038849621710779816852318505119327426213168494964113886299863","0"],"ay3":["0","0"],"balance1":["16000000","16000000","0"],"balance2":["0","15999000","0"],"balance3":["0","0"],"currentNumBatch":"1","ethAddr1":["721457446580647751014191829380889690493307935711","721457446580647751014191829380889690493307935711","0"],"ethAddr2":["0","721457446580647751014191829380889690493307935711","0"],"ethAddr3":["0","0"],"feeIdxs":["0","0"],"feePlanTokens":["0","0"],"fromBjjCompressed":[["1","1","1","0","1","0","1","1","0","1","1","0","0","0","1","0","0","1","0","0","0","0","0","1","1","1","1","1","0","0","1","0","1","0","1","1","1","1","1","0","0","1","0","1","0","0","0","0","1","0","1","0","0","0","1","1","0","0","1","0","0","0","0","0","0","1","0","1","0","0","1","0","1","1","1","0","1","0","1","0","1","1","1","1","1","1","0","0","1","0","0","0","1","0","1","0","0","1","0","0","1","1","0","1","0","0","0","1","1","1","1","0","0","0","1","1","0","1","0","1","1","0","1","0","1","1","0","1","1","0","1","1","0","1","1","0","0","1","0","0","0","0","0","1","1","1","0","1","1","1","0","0","0","0","1","1","0","1","1","1","1","0","0","1","1","1","0","0","1","0","1","0","1","0","1","0","1","0","1","1","1","0","0","0","1","0","1","1","1","0","0","0","1","1","0","1","1","1","1","0","1","1","1","0","1","1","1","1","1","1","1","0","1","1","0","0","1","1","0","1","0","0","0","1","0","0","0","1","0","1","1","0","1","0","0","0","0","1","0","1","0","0","0","0","1","1","0","1","1","0","0","0","0","1","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"fromEthAddr":["721457446580647751014191829380889690493307935711","0","0"],"fromIdx":["0","256","0"],"globalChainID":"0","imAccFeeOut":[["0","0"],["0","0"]],"imExitRoot":["0","0"],"imFinalAccFee":["0","0"],"imInitStateRootFee":"3212803832159212591526550848126062808026208063555125878245901046146545013161","imOnChain":["1","0"],"imOutIdx":["256","256"],"imStateRoot":["2999178063326948609414231200730958862089790119006655219527433501846141543551","3212803832159212591526550848126062808026208063555125878245901046146545013161"],"imStateRootFee":["3212803832159212591526550848126062808026208063555125878245901046146545013161"],"isOld0_1":["1","0","0"],"isOld0_2":["0","0","0"],"loadAmountF":["10400","0","0"],"maxNumBatch":["0","0","0"],"newAccount":["1","0","0"],"newExit":["0","0","0"],"nonce1":["0","0","0"],"nonce2":["0","1","0"],"nonce3":["0","0"],"oldKey1":["0","0","0"],"oldKey2":["0","0","0"],"oldLastIdx":"255","oldStateRoot":"0","oldValue1":["0","0","0"],"oldValue2":["0","0","0"],"onChain":["1","0","0"],"r8x":["0","13339118088097183560380359255316479838355724395928453439485234854234470298884","0"],"r8y":["0","12062876403986777372637801733000285846673058725183957648593976028822138986587","0"],"rqOffset":["0","0","0"],"rqToBjjAy":["0","0","0"],"rqToEthAddr":["0","0","0"],"rqTxCompressedDataV2":["0","0","0"],"s":["0","1429292460142966038093363510339656828866419125109324886747095533117015974779","0"],"siblings1":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings2":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings3":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"sign1":["0","0","0"],"sign2":["0","0","0"],"sign3":["0","0"],"toBjjAy":["0","0","0"],"toEthAddr":["0","0","0"],"toIdx":["0","256","0"],"tokenID1":["1","1","0"],"tokenID2":["0","1","0"],"tokenID3":["0","0"],"txCompressedData":["1461501637330902918203684832716283019659255211535","1483802382529433561627630154640673862706524841487","3322668559"],"txCompressedDataV2":["0","5271525021049092038181634317484288","0"]}` + assert.Equal(t, expected, string(s)) +} + +// TestZKInputs1: +// - 2 L1Tx of CreateAccountDeposit +// - 1 L2Tx with fees +func TestZKInputs1(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + defer assert.Nil(t, os.RemoveAll(dir)) + + nLevels := 16 + + sdb, err := NewStateDB(dir, TypeBatchBuilder, nLevels) + assert.Nil(t, err) + + // same values than in the js test + // skJsHex is equivalent to the 0000...0001 js private key in commonjs + sk0JsHex := "7eb258e61862aae75c6c1d1f7efae5006ffc9e4d5596a6ff95f3df4ea209ea7f" + sk0Js, err := hex.DecodeString(sk0JsHex) + require.Nil(t, err) + var sk0 babyjub.PrivateKey + copy(sk0[:], sk0Js) + bjj0 := sk0.Public() + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", bjj0.String()) + + sk1JsHex := "c005700f76f4b4cec710805c21595688648524df0a9d467afae537b7a7118819" + sk1Js, err := hex.DecodeString(sk1JsHex) + require.Nil(t, err) + var sk1 babyjub.PrivateKey + copy(sk1[:], sk1Js) + bjj1 := sk1.Public() + assert.Equal(t, "4d05c307400c65795f02db96b1b81c60386fd53e947d9d3f749f3d99b1853909", bjj1.String()) + + l1Txs := []common.L1Tx{ + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj0, + FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + { + FromIdx: 0, + DepositAmount: big.NewInt(16000000), + Amount: big.NewInt(0), + TokenID: 1, + FromBJJ: bjj1, + FromEthAddr: ethCommon.HexToAddress("0x2b5ad5c4795c026514f8317c7a215e218dccd6cf"), + ToIdx: 0, + Type: common.TxTypeCreateAccountDeposit, + UserOrigin: true, + }, + } + l2Txs := []common.PoolL2Tx{ + { + FromIdx: 256, + ToIdx: 256, + TokenID: 1, + Amount: big.NewInt(1000), + Nonce: 0, + Fee: 126, + Type: common.TxTypeTransfer, + }, + } + + toSign, err := l2Txs[0].HashToSign() + require.Nil(t, err) + sig := sk0.SignPoseidon(toSign) + l2Txs[0].Signature = sig.Compress() + + ptc := ProcessTxsConfig{ + NLevels: uint32(nLevels), + MaxTx: 3, + MaxL1Tx: 2, + MaxFeeTx: 2, + } + // skip first batch to do the test with BatchNum=1 + _, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil) + require.Nil(t, err) + + coordIdxs := []common.Idx{257} + ptOut, err := sdb.ProcessTxs(ptc, coordIdxs, l1Txs, nil, l2Txs) + require.Nil(t, err) + + // check expected account keys values from tx inputs + acc, err := sdb.GetAccount(common.Idx(256)) + require.Nil(t, err) + assert.Equal(t, "d746824f7d0ac5044a573f51b278acb56d823bec39551d1d7bf7378b68a1b021", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", acc.EthAddr.Hex()) + assert.Equal(t, "15999899", acc.Balance.String()) + acc, err = sdb.GetAccount(common.Idx(257)) + require.Nil(t, err) + assert.Equal(t, "4d05c307400c65795f02db96b1b81c60386fd53e947d9d3f749f3d99b1853909", acc.PublicKey.Compress().String()) + assert.Equal(t, "0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF", acc.EthAddr.Hex()) + assert.Equal(t, "16000101", acc.Balance.String()) + + // check that there no exist more accounts + _, err = sdb.GetAccount(common.Idx(258)) + require.NotNil(t, err) + + debug := false + // debug = true + if debug { + printZKInputs(t, ptOut.ZKInputs) + } + + toHash, err := ptOut.ZKInputs.ToHashGlobalData() + require.Nil(t, err) + assert.Equal(t, "0000000000ff0000000001010000000000000000000000000000000000000000000000000000000000000000036d607b790b93bb1768d5390803b5a4a1f77e46755f57900930b14454faf95c00000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d00000000000028a000000000000100000000000000000000000000000000000000000100010003e87e01010000000000000001", hex.EncodeToString(toHash)) + + h, err := ptOut.ZKInputs.HashGlobalData() + require.Nil(t, err) + assert.Equal(t, "11039366437749764484706691779656824178800407917434257418748834397596260744468", h.String()) + + s, err := json.Marshal(ptOut.ZKInputs) + require.Nil(t, err) + + // the 'expected' data has been checked with the circom circuits + expected := `{"auxFromIdx":["256","257","0"],"auxToIdx":["0","0","0"],"ay1":["15238403086306505038849621710779816852318505119327426213168494964113886299863","4172448640254579435434214421479401747968866348490029667576411173067925161293","15238403086306505038849621710779816852318505119327426213168494964113886299863"],"ay2":["0","0","15238403086306505038849621710779816852318505119327426213168494964113886299863"],"ay3":["4172448640254579435434214421479401747968866348490029667576411173067925161293","0"],"balance1":["16000000","16000000","16000000"],"balance2":["0","0","15998899"],"balance3":["16000000","0"],"currentNumBatch":"1","ethAddr1":["721457446580647751014191829380889690493307935711","247512291986854564435551364600938690683113101007","721457446580647751014191829380889690493307935711"],"ethAddr2":["0","0","721457446580647751014191829380889690493307935711"],"ethAddr3":["247512291986854564435551364600938690683113101007","0"],"feeIdxs":["257","0"],"feePlanTokens":["1","0"],"fromBjjCompressed":[["1","1","1","0","1","0","1","1","0","1","1","0","0","0","1","0","0","1","0","0","0","0","0","1","1","1","1","1","0","0","1","0","1","0","1","1","1","1","1","0","0","1","0","1","0","0","0","0","1","0","1","0","0","0","1","1","0","0","1","0","0","0","0","0","0","1","0","1","0","0","1","0","1","1","1","0","1","0","1","0","1","1","1","1","1","1","0","0","1","0","0","0","1","0","1","0","0","1","0","0","1","1","0","1","0","0","0","1","1","1","1","0","0","0","1","1","0","1","0","1","1","0","1","0","1","1","0","1","1","0","1","1","0","1","1","0","0","1","0","0","0","0","0","1","1","1","0","1","1","1","0","0","0","0","1","1","0","1","1","1","1","0","0","1","1","1","0","0","1","0","1","0","1","0","1","0","1","0","1","1","1","0","0","0","1","0","1","1","1","0","0","0","1","1","0","1","1","1","1","0","1","1","1","0","1","1","1","1","1","1","1","0","1","1","0","0","1","1","0","1","0","0","0","1","0","0","0","1","0","1","1","0","1","0","0","0","0","1","0","1","0","0","0","0","1","1","0","1","1","0","0","0","0","1","0","0"],["1","0","1","1","0","0","1","0","1","0","1","0","0","0","0","0","1","1","0","0","0","0","1","1","1","1","1","0","0","0","0","0","0","0","0","0","0","0","1","0","0","0","1","1","0","0","0","0","1","0","1","0","0","1","1","0","1","0","0","1","1","1","1","0","1","1","1","1","1","0","1","0","0","1","0","0","0","0","0","0","1","1","0","1","1","0","1","1","0","1","1","0","1","0","0","1","1","0","0","0","1","1","0","1","0","0","0","1","1","1","0","1","0","0","1","1","1","0","0","0","0","0","0","0","0","1","1","0","0","0","0","1","1","1","0","0","1","1","1","1","0","1","1","0","1","0","1","0","1","0","1","1","0","1","1","1","1","1","0","0","0","0","1","0","1","0","0","1","1","0","1","1","1","1","1","0","1","0","1","1","1","0","0","1","1","1","1","1","1","1","0","0","0","0","1","0","1","1","1","0","1","1","1","1","1","0","0","1","1","0","1","1","1","1","0","0","1","0","0","1","1","0","0","1","1","0","0","0","1","1","0","1","1","0","1","0","0","0","0","1","1","0","0","1","1","1","0","0","1","0","0","1","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"fromEthAddr":["721457446580647751014191829380889690493307935711","247512291986854564435551364600938690683113101007","0"],"fromIdx":["0","0","256"],"globalChainID":"0","imAccFeeOut":[["0","0"],["0","0"]],"imExitRoot":["0","0"],"imFinalAccFee":["101","0"],"imInitStateRootFee":"10660728613879129016661596154319504485937170756181586060561759832613498905432","imOnChain":["1","1"],"imOutIdx":["256","257"],"imStateRoot":["2999178063326948609414231200730958862089790119006655219527433501846141543551","13160175861809095962915811919507877524206523306071085047160493107056995190544"],"imStateRootFee":["1550190772280924834409423240867892593473592863918771212295716656664630983004"],"isOld0_1":["1","0","0"],"isOld0_2":["0","0","0"],"loadAmountF":["10400","10400","0"],"maxNumBatch":["0","0","0"],"newAccount":["1","1","0"],"newExit":["0","0","0"],"nonce1":["0","0","0"],"nonce2":["0","0","1"],"nonce3":["0","0"],"oldKey1":["0","256","0"],"oldKey2":["0","0","0"],"oldLastIdx":"255","oldStateRoot":"0","oldValue1":["0","9733782510199048326382833205201407219982604211594942097825192094127807440165","0"],"oldValue2":["0","0","0"],"onChain":["1","1","0"],"r8x":["0","0","16795818329006817411605347777151783287113601795569690834743955502344582990059"],"r8y":["0","0","21153110871938011270027204820675751452345817312713349225139208384264949654114"],"rqOffset":["0","0","0"],"rqToBjjAy":["0","0","0"],"rqToEthAddr":["0","0","0"],"rqTxCompressedDataV2":["0","0","0"],"s":["0","0","1550352334297856444344240780544275542131334387040150478134835458055364079268"],"siblings1":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["6975841694765113541634698345295957238501610055097872059913911260522365532165","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings2":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["6975841694765113541634698345295957238501610055097872059913911260522365532165","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"siblings3":[["9827704113668630072730115158977131501210702363656902211840117643154933433410","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]],"sign1":["0","0","0"],"sign2":["0","0","0"],"sign3":["0","0"],"toBjjAy":["0","0","0"],"toEthAddr":["0","0","0"],"toIdx":["0","0","256"],"tokenID1":["1","1","1"],"tokenID2":["0","0","1"],"tokenID3":["1","0"],"txCompressedData":["1461501637330902918203684832716283019659255211535","1461501637330902918203684832716283019659255211535","869620039695611037216780722449287736442401358123623346624340758723552783"],"txCompressedDataV2":["0","0","3089511010385631938450432878260044363267416251956459471104"]}` + assert.Equal(t, expected, string(s)) +}