diff --git a/txprocessor/txprocessor.go b/txprocessor/txprocessor.go index 302958c..db9810f 100644 --- a/txprocessor/txprocessor.go +++ b/txprocessor/txprocessor.go @@ -340,6 +340,7 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat tp.zki.ISOutIdx[tp.i] = tp.s.CurrentIdx().BigInt() tp.zki.ISStateRoot[tp.i] = tp.s.MT.Root().BigInt() + tp.zki.ISExitRoot[tp.i] = exitTree.Root().BigInt() tp.i++ } } @@ -1333,7 +1334,7 @@ func (tp *TxProcessor) applyExit(coordIdxsMap map[common.TokenID]common.Idx, } return exitAccount, true, nil } else if err != nil { - return exitAccount, false, tracerr.Wrap(err) + return nil, false, tracerr.Wrap(err) } // 1b. if idx already exist in exitTree: diff --git a/txprocessor/zkinputsgen_test.go b/txprocessor/zkinputsgen_test.go index b7a2a4c..929023e 100644 --- a/txprocessor/zkinputsgen_test.go +++ b/txprocessor/zkinputsgen_test.go @@ -1193,3 +1193,95 @@ func TestZKInputsDepositTransferDifferentTokenIDs(t *testing.T) { expected := `{"amountF":["50","0","0"],"auxFromIdx":["0","0","0"],"auxToIdx":["0","0","0"],"ay1":["14382649545529405976710664157356364657039027681269256663271478725131562622080","0","0"],"ay2":["21759653464180282217133439550283093276794317614482080451288933258136700169296","0","0"],"ay3":["0","0"],"balance1":["100","0","0"],"balance2":["100","0","0"],"balance3":["0","0"],"currentNumBatch":"2","ethAddr1":["721457446580647751014191829380889690493307935711","0","0"],"ethAddr2":["247512291986854564435551364600938690683113101007","0","0"],"ethAddr3":["0","0"],"feeIdxs":["0","0"],"feePlanTokens":["0","0"],"fromBjjCompressed":[["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","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":["256","0","0"],"globalChainID":"1","imAccFeeOut":[["0","0"],["0","0"]],"imExitRoot":["0","0"],"imFinalAccFee":["0","0"],"imInitStateRootFee":"19417836826297191229974288228054713661786372819574644703085140765989632164657","imOnChain":["1","0"],"imOutIdx":["257","257"],"imStateRoot":["19417836826297191229974288228054713661786372819574644703085140765989632164657","19417836826297191229974288228054713661786372819574644703085140765989632164657"],"imStateRootFee":["19417836826297191229974288228054713661786372819574644703085140765989632164657"],"isOld0_1":["0","0","0"],"isOld0_2":["0","0","0"],"loadAmountF":["200","0","0"],"maxNumBatch":["0","0","0"],"newAccount":["0","0","0"],"newExit":["0","0","0"],"nonce1":["0","0","0"],"nonce2":["0","0","0"],"nonce3":["0","0"],"oldKey1":["0","0","0"],"oldKey2":["0","0","0"],"oldLastIdx":"257","oldStateRoot":"17665447466292249227040737494607250348185977581188521003423431404868792035125","oldValue1":["0","0","0"],"oldValue2":["0","0","0"],"onChain":["1","0","0"],"r8x":["0","0","0"],"r8y":["0","0","0"],"rqOffset":["0","0","0"],"rqToBjjAy":["0","0","0"],"rqToEthAddr":["0","0","0"],"rqTxCompressedDataV2":["0","0","0"],"s":["0","0","0"],"siblings1":[["19804266311162315075341193157175404055837431307331873037968288519104597644492","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","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":[["21767257421687034543328009757734962886927034168420617435345607097345204956413","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["0","0","0","0","0","0","0","0","0","0","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":["257","0","0"],"tokenID1":["0","0","0"],"tokenID2":["1","0","0"],"tokenID3":["0","0"],"txCompressedData":["20361637766166006819142450800143","7617635855","7617635855"],"txCompressedDataV2":["0","0","0"]}` //nolint:lll assert.Equal(t, expected, string(s)) } + +func TestZKInputsL1CoordinatorTxsAfterL1Exit(t *testing.T) { + // Test to check that the ISExitRoot values for the L1CoordinatorTx + // slots, after a L1User Exit tx, have the expected value (!=0) + dir, err := ioutil.TempDir("", "tmpdb") + require.NoError(t, err) + defer assert.NoError(t, os.RemoveAll(dir)) + + nLevels := 16 + sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128, + Type: statedb.TypeBatchBuilder, NLevels: nLevels}) + assert.NoError(t, err) + + chainID := uint16(1) + + tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx) + + set := ` + Type: Blockchain + + CreateAccountDeposit(0) A: 100 + + > batchL1 // batch1: freeze L1User{1} + > batchL1 // batch2: forge L1User{1} + + ForceExit(0) A: 10 + + > batchL1 // batch1: freeze L1User{1} + + // Coordinator creates needed 'To' accounts for the L2Txs + CreateAccountCoordinator(0) B + CreateAccountCoordinator(0) C + + > batchL1 // batch3: forge L1User{1}, L1Coord{2} + > block + ` + blocks, err := tc.GenerateBlocks(set) + require.NoError(t, err) + err = tc.FillBlocksExtra(blocks, &til.ConfigExtra{}) + require.NoError(t, err) + err = tc.FillBlocksForgedL1UserTxs(blocks) + require.NoError(t, err) + + config := Config{ + NLevels: uint32(nLevels), + MaxTx: 5, + MaxL1Tx: 3, + MaxFeeTx: 3, + ChainID: chainID, + } + tp := NewTxProcessor(sdb, config) + + // process Batch2: + ptOut, err := tp.ProcessTxs(nil, blocks[0].Rollup.Batches[1].L1UserTxs, nil, nil) + require.NoError(t, err) + assert.Equal(t, + "601907123714740672507543219135850785231457721026220266509483476465720317012", + ptOut.ZKInputs.Metadata.NewStateRootRaw.BigInt().String()) + checkBalanceByIdx(t, tp.s, 256, "100") // A + + // batch3 + batchPoolL2 := ` + Type: PoolL2 + PoolTransferToEthAddr(0) A-B: 10 (126) + PoolTransferToEthAddr(0) A-C: 10 (126)` + poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2) + require.NoError(t, err) + + // process Batch4: + l1UserTxs := blocks[0].Rollup.Batches[3].L1UserTxs + ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, poolL2Txs) + require.NoError(t, err) + assert.Equal(t, + "17775331426946444434905404877316765678788279057663351606525063640213765390628", + ptOut.ZKInputs.Metadata.NewStateRootRaw.BigInt().String()) + checkBalanceByIdx(t, tp.s, 256, "68") // A + checkBalanceByIdx(t, tp.s, 257, "10") // B + + // Check that all the ISExitRoot values have the expected value, and + // that there are no 0 for the L1Coordinator tx slots after the L1User + // slots + for i := 0; i < len(ptOut.ZKInputs.ISExitRoot); i++ { + assert.Equal(t, "14329759303391468223438874789317921522067594445474390443816827472846339238908", ptOut.ZKInputs.ISExitRoot[i].String()) + } + + h, err := ptOut.ZKInputs.HashGlobalData() + require.NoError(t, err) + assert.Equal(t, + "21642187205693687710998688332288948999415781181212696454636425754460316513902", + h.String()) + // printZKInputs(t, ptOut.ZKInputs) +}