diff --git a/coordinator/pipeline.go b/coordinator/pipeline.go index c8b2108..d272587 100644 --- a/coordinator/pipeline.go +++ b/coordinator/pipeline.go @@ -407,11 +407,6 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e batchInfo.Debug.StartTimestamp = now batchInfo.Debug.StartBlockNum = p.stats.Eth.LastBlock.Num + 1 - selectionCfg := &txselector.SelectionConfig{ - MaxL1UserTxs: common.RollupConstMaxL1UserTx, - TxProcessorConfig: p.cfg.TxProcessorConfig, - } - var poolL2Txs []common.PoolL2Tx var discardedL2Txs []common.PoolL2Tx var l1UserTxsExtra, l1CoordTxs []common.L1Tx @@ -442,14 +437,14 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e return nil, tracerr.Wrap(err) } coordIdxs, auths, l1UserTxsExtra, l1CoordTxs, poolL2Txs, discardedL2Txs, err = - p.txSelector.GetL1L2TxSelection(selectionCfg, l1UserTxs) + p.txSelector.GetL1L2TxSelection(p.cfg.TxProcessorConfig, l1UserTxs) if err != nil { return nil, tracerr.Wrap(err) } } else { // 2b: only L2 txs coordIdxs, auths, l1CoordTxs, poolL2Txs, discardedL2Txs, err = - p.txSelector.GetL2TxSelection(selectionCfg) + p.txSelector.GetL2TxSelection(p.cfg.TxProcessorConfig) if err != nil { return nil, tracerr.Wrap(err) } diff --git a/test/zkproof/flows_test.go b/test/zkproof/flows_test.go index 2d80b45..d956971 100644 --- a/test/zkproof/flows_test.go +++ b/test/zkproof/flows_test.go @@ -137,10 +137,6 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { // add tokens to HistoryDB to avoid breaking FK constrains addTokens(t, tc, l2DBTxSel.DB()) - selectionConfig := &txselector.SelectionConfig{ - MaxL1UserTxs: 100, // TODO - TxProcessorConfig: txprocConfig, - } configBatch := &batchbuilder.ConfigBatch{ // ForgerAddress: TxProcessorConfig: txprocConfig, @@ -160,7 +156,7 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { } // TxSelector select the transactions for the next Batch coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -184,7 +180,7 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum]) // TxSelector select the transactions for the next Batch coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -213,7 +209,7 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum]) // TxSelector select the transactions for the next Batch coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -240,7 +236,7 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum]) // TxSelector select the transactions for the next Batch coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -260,7 +256,7 @@ func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) { l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum]) // TxSelector select the transactions for the next Batch coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -315,10 +311,6 @@ func TestZKInputsExitWithFee0(t *testing.T) { // add tokens to HistoryDB to avoid breaking FK constrains addTokens(t, tc, l2DBTxSel.DB()) - selectionConfig := &txselector.SelectionConfig{ - MaxL1UserTxs: 100, - TxProcessorConfig: txprocConfig, - } configBatch := &batchbuilder.ConfigBatch{ TxProcessorConfig: txprocConfig, } @@ -327,7 +319,7 @@ func TestZKInputsExitWithFee0(t *testing.T) { // TxSelector select the transactions for the next Batch l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum]) coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs) require.NoError(t, err) // BatchBuilder build Batch zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) @@ -350,7 +342,7 @@ func TestZKInputsExitWithFee0(t *testing.T) { require.NoError(t, err) addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := - txsel.GetL1L2TxSelection(selectionConfig, nil) + txsel.GetL1L2TxSelection(txprocConfig, nil) require.NoError(t, err) assert.Equal(t, 1, len(coordIdxs)) assert.Equal(t, 0, len(oL1UserTxs)) diff --git a/txselector/txselector.go b/txselector/txselector.go index f1c0b8f..c4c27ef 100644 --- a/txselector/txselector.go +++ b/txselector/txselector.go @@ -27,16 +27,6 @@ type CoordAccount struct { AccountCreationAuth []byte // signature in byte array format } -// SelectionConfig contains the parameters of configuration of the selection of -// transactions for the next batch -type SelectionConfig struct { - // MaxL1UserTxs is the maximum L1-user-tx for a batch - MaxL1UserTxs uint64 - - // TxProcessorConfig contains the config for ProcessTxs - TxProcessorConfig txprocessor.Config -} - // TxSelector implements all the functionalities to select the txs for the next // batch type TxSelector struct { @@ -131,7 +121,7 @@ func (txsel *TxSelector) coordAccountForTokenID(l1CoordinatorTxs []common.L1Tx, // but there is a transactions to them and the authorization of account // creation exists. The L1UserTxs, L1CoordinatorTxs, PoolL2Txs that will be // included in the next batch. -func (txsel *TxSelector) GetL2TxSelection(selectionConfig *SelectionConfig) ([]common.Idx, +func (txsel *TxSelector) GetL2TxSelection(selectionConfig txprocessor.Config) ([]common.Idx, [][]byte, []common.L1Tx, []common.PoolL2Tx, []common.PoolL2Tx, error) { metricGetL2TxSelection.Inc() coordIdxs, accCreationAuths, _, l1CoordinatorTxs, l2Txs, @@ -148,7 +138,7 @@ func (txsel *TxSelector) GetL2TxSelection(selectionConfig *SelectionConfig) ([]c // but there is a transactions to them and the authorization of account // creation exists. The L1UserTxs, L1CoordinatorTxs, PoolL2Txs that will be // included in the next batch. -func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig, +func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig txprocessor.Config, l1UserTxs []common.L1Tx) ([]common.Idx, [][]byte, []common.L1Tx, []common.L1Tx, []common.PoolL2Tx, []common.PoolL2Tx, error) { metricGetL1L2TxSelection.Inc() @@ -158,7 +148,7 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig, discardedL2Txs, tracerr.Wrap(err) } -func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, +func (txsel *TxSelector) getL1L2TxSelection(selectionConfig txprocessor.Config, l1UserTxs []common.L1Tx) ([]common.Idx, [][]byte, []common.L1Tx, []common.L1Tx, []common.PoolL2Tx, []common.PoolL2Tx, error) { // WIP.0: the TxSelector is not optimized and will need a redesign. The @@ -177,7 +167,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, } txselStateDB := txsel.localAccountsDB.StateDB - tp := txprocessor.NewTxProcessor(txselStateDB, selectionConfig.TxProcessorConfig) + tp := txprocessor.NewTxProcessor(txselStateDB, selectionConfig) // Process L1UserTxs for i := 0; i < len(l1UserTxs); i++ { @@ -188,16 +178,16 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, } } - // discardedL2Txs contains an array of the L2Txs that have not been selected in this Batch - var l1CoordinatorTxs []common.L1Tx positionL1 := len(l1UserTxs) var accAuths [][]byte - // sort l2TxsRaw (cropping at MaxTx at this point) - l2Txs0, discardedL2Txs := txsel.getL2Profitable(l2TxsRaw, selectionConfig.TxProcessorConfig.MaxTx) + // Sort l2TxsRaw (cropping at MaxTx at this point). + // discardedL2Txs contains an array of the L2Txs that have not been + // selected in this Batch. + l2Txs0, discardedL2Txs := txsel.getL2Profitable(l2TxsRaw, selectionConfig.MaxTx) for i := range discardedL2Txs { - discardedL2Txs[i].Info = "Tx not selected due to low absolute fee" + discardedL2Txs[i].Info = "Tx not selected due to low absolute fee (does not fit inside the profitable set)" } noncesMap := make(map[common.Idx]common.Nonce) @@ -229,7 +219,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, } if newL1CoordTx != nil { // if there is no space for the L1CoordinatorTx, discard the L2Tx - if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1UserTxs)-len(l1UserTxs) { + if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-len(l1UserTxs) { // discard L2Tx, and update Info parameter of // the tx, and add it to the discardedTxs array l2Txs0[i].Info = "Tx not selected because the L2Tx depends on a " + @@ -266,9 +256,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, } // check if Nonce is correct nonce := noncesMap[l2Txs[i].FromIdx] - if l2Txs[i].Nonce == nonce { - noncesMap[l2Txs[i].FromIdx]++ - } else { + if l2Txs[i].Nonce != nonce { // not valid Nonce at tx. Discard L2Tx, and update Info // parameter of the tx, and add it to the discardedTxs // array @@ -371,6 +359,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, // valid txs (of Exit type) validTxs = append(validTxs, l2Txs[i]) } + noncesMap[l2Txs[i].FromIdx]++ } // Process L1CoordinatorTxs @@ -413,7 +402,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, }) // get most profitable L2-tx - maxL2Txs := int(selectionConfig.TxProcessorConfig.MaxTx) - + maxL2Txs := int(selectionConfig.MaxTx) - len(l1UserTxs) - len(l1CoordinatorTxs) selectedL2Txs := validTxs @@ -427,14 +416,10 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, // the error can be due not valid tx data, or due other // cases (such as StateDB error). At this initial // version of the TxSelector, we discard the L2Tx and - // log the error, assuming that this will be iterated - // in a near future. - log.Error(err) - // Discard L2Tx, and update Info parameter of the tx, - // and add it to the discardedTxs array - selectedL2Txs[i].Info = fmt.Sprintf("Tx not selected (in ProcessL2Tx) due to %s", err.Error()) - discardedL2Txs = append(discardedL2Txs, selectedL2Txs[i]) - continue + // log the error, assuming that this will be iterated in + // a near future. + return nil, nil, nil, nil, nil, nil, + tracerr.Wrap(fmt.Errorf("TxSelector: txprocessor.ProcessL2Tx: %w", err)) } finalL2Txs = append(finalL2Txs, selectedL2Txs[i]) } @@ -480,7 +465,7 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig *SelectionConfig, // l1CoordinatorTxs array, and then the PoolL2Tx is added into the validTxs // array. func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs []common.PoolL2Tx, - selectionConfig *SelectionConfig, nL1UserTxs int, l1CoordinatorTxs []common.L1Tx, + selectionConfig txprocessor.Config, nL1UserTxs int, l1CoordinatorTxs []common.L1Tx, positionL1 int, l2Tx common.PoolL2Tx) (*common.PoolL2Tx, *common.L1Tx, *common.AccountCreationAuth, error) { // if L2Tx needs a new L1CoordinatorTx of CreateAccount type, and a @@ -582,7 +567,7 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs []common.PoolL2Tx, Type: common.TxTypeCreateAccountDeposit, } } - if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1UserTxs)-nL1UserTxs { + if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-nL1UserTxs { // L2Tx discarded return nil, nil, nil, tracerr.Wrap(fmt.Errorf("L2Tx discarded due to no available slots " + "for L1CoordinatorTx to create a new account for receiver of L2Tx")) diff --git a/txselector/txselector_test.go b/txselector/txselector_test.go index 34a41db..deb82e0 100644 --- a/txselector/txselector_test.go +++ b/txselector/txselector_test.go @@ -174,17 +174,13 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { MaxL1Tx: 10, ChainID: chainID, } - selectionConfig := &SelectionConfig{ - MaxL1UserTxs: 5, - TxProcessorConfig: tpc, - } // coordIdxs, accAuths, l1UserTxs, l1CoordTxs, l2Txs, err log.Debug("block:0 batch:1") l1UserTxs := []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -195,7 +191,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { log.Debug("block:0 batch:2") l1UserTxs = []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -206,7 +202,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { log.Debug("block:0 batch:3") l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 2, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -219,7 +215,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { log.Debug("block:0 batch:4") l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 1, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -233,7 +229,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { log.Debug("block:0 batch:5") l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -247,7 +243,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { log.Debug("block:0 batch:6") l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 1, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -281,7 +277,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress())) l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum]) coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, []common.Idx{261, 262}, coordIdxs) assert.Equal(t, txsel.coordAccount.AccountCreationAuth, accAuths[0]) @@ -329,7 +325,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { assert.True(t, l2TxsFromDB[3].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress())) l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum]) coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, []common.Idx{261, 262}, coordIdxs) assert.Equal(t, 0, len(accAuths)) @@ -372,7 +368,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress())) l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum]) coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, []common.Idx{262}, coordIdxs) assert.Equal(t, 0, len(accAuths)) @@ -405,8 +401,8 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) { CreateAccountDeposit(0) A: 100 CreateAccountDeposit(0) B: 100 - > batchL1 // freeze L1User{1} - > batchL1 // forge L1User{1} + > batchL1 // freeze L1User{3} + > batchL1 // forge L1User{3} > block ` @@ -432,13 +428,9 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) { MaxL1Tx: 10, ChainID: chainID, } - selectionConfig := &SelectionConfig{ - MaxL1UserTxs: 5, - TxProcessorConfig: tpc, - } // batch1 l1UserTxs := []common.L1Tx{} - _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) // 1st TransferToEthAddr expectedTxID0 := "0x028847b86613c0b70be18c8622119ed045b42e4e47d7938fa90bb3d1dc14928965" @@ -460,7 +452,7 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) { l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 3, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -490,7 +482,7 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) { l1UserTxs = []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -509,7 +501,7 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) { // initial PoolExit, which now is valid as B has enough Balance l1UserTxs = []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) assert.Equal(t, 0, len(oL1CoordTxs)) @@ -534,8 +526,8 @@ func TestTransferToBjj(t *testing.T) { CreateAccountDeposit(0) B: 1000 CreateAccountDeposit(1) B: 1000 - > batchL1 // freeze L1User{1} - > batchL1 // forge L1User{1} + > batchL1 // freeze L1User{4} + > batchL1 // forge L1User{4} > block ` @@ -560,14 +552,10 @@ func TestTransferToBjj(t *testing.T) { MaxL1Tx: 10, ChainID: chainID, } - selectionConfig := &SelectionConfig{ - MaxL1UserTxs: 5, - TxProcessorConfig: tpc, - } // batch1 to freeze L1UserTxs that will create some accounts with // positive balance l1UserTxs := []common.L1Tx{} - _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) // Transfer is ToBJJ to a BJJ-only account that doesn't exist @@ -585,7 +573,7 @@ func TestTransferToBjj(t *testing.T) { l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 4, len(oL1UserTxs)) // We expect the coordinator to add an L1CoordTx to create an account for the recipient of the l2tx @@ -613,7 +601,7 @@ func TestTransferToBjj(t *testing.T) { l1UserTxs = []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) // Since the BJJ-only account B already exists, the coordinator doesn't add any L1CoordTxs @@ -641,7 +629,7 @@ func TestTransferToBjj(t *testing.T) { l1UserTxs = []common.L1Tx{} _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 0, len(oL1UserTxs)) // We expect the coordinator to add an L1CoordTx to create an account @@ -670,8 +658,8 @@ func TestTransferManyFromSameAccount(t *testing.T) { CreateAccountDeposit(0) A: 1000 CreateAccountDeposit(0) B: 1000 - > batchL1 // freeze L1User{1} - > batchL1 // forge L1User{1} + > batchL1 // freeze L1User{3} + > batchL1 // forge L1User{3} > block ` @@ -694,17 +682,12 @@ func TestTransferManyFromSameAccount(t *testing.T) { MaxL1Tx: 10, ChainID: chainID, } - selectionConfig := &SelectionConfig{ - MaxL1UserTxs: 5, - TxProcessorConfig: tpc, - } // batch1 to freeze L1UserTxs l1UserTxs := []common.L1Tx{} - _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) // 8 transfers from the same account - batchPoolL2 := ` Type: PoolL2 PoolTransfer(0) A-B: 10 (126) // 1 @@ -732,7 +715,7 @@ func TestTransferManyFromSameAccount(t *testing.T) { // batch 2 to crate some accounts with positive balance, and do 8 L2Tx transfers from account A l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum]) _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := - txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + txsel.GetL1L2TxSelection(tpc, l1UserTxs) require.NoError(t, err) assert.Equal(t, 3, len(oL1UserTxs)) require.Equal(t, 0, len(oL1CoordTxs)) @@ -743,3 +726,120 @@ func TestTransferManyFromSameAccount(t *testing.T) { txsel.localAccountsDB.CurrentBatch()) require.NoError(t, err) } + +func TestPoolL2TxInvalidNonces(t *testing.T) { + // This test recreates the case where L2Txs of type TransferToEthAddr + // for non existing accounts are not selected due not enough space for + // the needed L1CoordinatorTxs (of account creation). + + set := ` + Type: Blockchain + + CreateAccountDeposit(0) Coord: 0 + CreateAccountDeposit(0) A: 100000 + CreateAccountDeposit(0) B: 10000 + + > batchL1 // Batch1: freeze L1User{3} + > batchL1 // Batch2: forge L1User{3} + > block + ` + + chainID := uint16(0) + tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocks(set) + assert.NoError(t, err) + + hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6") + txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"]) + + // restart nonces of TilContext, as will be set by generating directly + // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs + tc.RestartNonces() + + tpc := txprocessor.Config{ + NLevels: 16, + MaxFeeTx: 10, + MaxTx: 20, + MaxL1Tx: 3, + ChainID: chainID, + } + // batch1 to freeze L1UserTxs + l1UserTxs := []common.L1Tx{} + _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs) + require.NoError(t, err) + + batchPoolL2 := ` + Type: PoolL2 + PoolTransferToEthAddr(0) B-C: 10 (126) + PoolTransfer(0) B-A: 10 (126) + PoolTransferToEthAddr(0) B-D: 10 (126) + PoolTransfer(0) B-A: 10 (126) + PoolTransferToEthAddr(0) B-E: 10 (126) + PoolTransfer(0) B-A: 10 (126) + PoolTransferToEthAddr(0) B-F: 10 (126) + PoolTransfer(0) B-A: 10 (126) + PoolTransferToEthAddr(0) B-G: 10 (126) + PoolTransfer(0) B-A: 10 (126) + ` + poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2) + require.NoError(t, err) + require.Equal(t, 10, len(poolL2Txs)) + + // add AccountCreationAuths that will be used at the next batch + _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "C") + _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "D") + _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "E") + _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "F") + _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "G") + + // add the PoolL2Txs to the l2DB + addL2Txs(t, txsel, poolL2Txs) + // batch 2 to crate the accounts (from L1UserTxs) + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum]) + + // select L1 & L2 txs + _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := + txsel.GetL1L2TxSelection(tpc, l1UserTxs) + require.NoError(t, err) + require.Equal(t, 3, len(oL1UserTxs)) + require.Equal(t, 0, len(oL1CoordTxs)) + require.Equal(t, 2, len(oL2Txs)) + require.Equal(t, 8, len(discardedL2Txs)) + require.Equal(t, 0, len(accAuths)) + + err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), + txsel.localAccountsDB.CurrentBatch()) + require.NoError(t, err) + + // batch 3 + l1UserTxs = []common.L1Tx{} + _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = + txsel.GetL1L2TxSelection(tpc, l1UserTxs) + require.NoError(t, err) + + require.Equal(t, 0, len(oL1UserTxs)) + require.Equal(t, 3, len(oL1CoordTxs)) + require.Equal(t, 6, len(oL2Txs)) + require.Equal(t, 2, len(discardedL2Txs)) + require.Equal(t, 3, len(accAuths)) + + err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), + txsel.localAccountsDB.CurrentBatch()) + require.NoError(t, err) + + // batch 4 + l1UserTxs = []common.L1Tx{} + _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = + txsel.GetL1L2TxSelection(tpc, l1UserTxs) + require.NoError(t, err) + + require.Equal(t, 0, len(oL1UserTxs)) + require.Equal(t, 1, len(oL1CoordTxs)) + require.Equal(t, 2, len(oL2Txs)) + require.Equal(t, 0, len(discardedL2Txs)) + require.Equal(t, 1, len(accAuths)) + + err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), + txsel.localAccountsDB.CurrentBatch()) + require.NoError(t, err) +}