From 7f46c3028e48767af48464fa91648804d3ab32ef Mon Sep 17 00:00:00 2001 From: arnaucube Date: Fri, 15 Jan 2021 19:25:11 +0100 Subject: [PATCH] Add tests connecting TxSelector, BatchBuilder, ZKInputs, ProofServer - Add tests connecting TxSelector, BatchBuilder, ZKInputs, ProofServer - Added test to check that the signatures of the PoolL2Txs from the L2DB pool can be verified, to check that the parameters of the PoolL2Tx match the original parameters signed before inserting them into the L2DB --- batchbuilder/batchbuilder.go | 13 +- batchbuilder/batchbuilder_test.go | 2 +- coordinator/coordinator_test.go | 2 +- coordinator/pipeline.go | 3 +- db/l2db/l2db_test.go | 3 +- node/node.go | 2 +- test/zkproof/flows_test.go | 247 ++++++++++++++++++++++++++++++ test/zkproof/zkproof_test.go | 94 ++++++------ txprocessor/zkinputsgen_test.go | 2 +- txselector/txselector_test.go | 74 +++++---- 10 files changed, 347 insertions(+), 95 deletions(-) create mode 100644 test/zkproof/flows_test.go diff --git a/batchbuilder/batchbuilder.go b/batchbuilder/batchbuilder.go index 545ef7f..4515efc 100644 --- a/batchbuilder/batchbuilder.go +++ b/batchbuilder/batchbuilder.go @@ -1,7 +1,6 @@ package batchbuilder import ( - ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/db/statedb" "github.com/hermeznetwork/hermez-node/txprocessor" @@ -18,19 +17,17 @@ type ConfigCircuit struct { // BatchBuilder implements the batch builder type, which contains the // functionalities type BatchBuilder struct { - localStateDB *statedb.LocalStateDB - configCircuits []ConfigCircuit + localStateDB *statedb.LocalStateDB } // ConfigBatch contains the batch configuration type ConfigBatch struct { - ForgerAddress ethCommon.Address TxProcessorConfig txprocessor.Config } // NewBatchBuilder constructs a new BatchBuilder, and executes the bb.Reset // method -func NewBatchBuilder(dbpath string, synchronizerStateDB *statedb.StateDB, configCircuits []ConfigCircuit, batchNum common.BatchNum, nLevels uint64) (*BatchBuilder, error) { +func NewBatchBuilder(dbpath string, synchronizerStateDB *statedb.StateDB, batchNum common.BatchNum, nLevels uint64) (*BatchBuilder, error) { localStateDB, err := statedb.NewLocalStateDB(dbpath, 128, synchronizerStateDB, statedb.TypeBatchBuilder, int(nLevels)) if err != nil { @@ -38,8 +35,7 @@ func NewBatchBuilder(dbpath string, synchronizerStateDB *statedb.StateDB, config } bb := BatchBuilder{ - localStateDB: localStateDB, - configCircuits: configCircuits, + localStateDB: localStateDB, } err = bb.Reset(batchNum, true) @@ -56,8 +52,7 @@ func (bb *BatchBuilder) Reset(batchNum common.BatchNum, fromSynchronizer bool) e // BuildBatch takes the transactions and returns the common.ZKInputs of the next batch func (bb *BatchBuilder) BuildBatch(coordIdxs []common.Idx, configBatch *ConfigBatch, l1usertxs, - l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx, - tokenIDs []common.TokenID) (*common.ZKInputs, error) { + l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx) (*common.ZKInputs, error) { bbStateDB := bb.localStateDB.StateDB tp := txprocessor.NewTxProcessor(bbStateDB, configBatch.TxProcessorConfig) diff --git a/batchbuilder/batchbuilder_test.go b/batchbuilder/batchbuilder_test.go index 7600a67..550f5e6 100644 --- a/batchbuilder/batchbuilder_test.go +++ b/batchbuilder/batchbuilder_test.go @@ -21,6 +21,6 @@ func TestBatchBuilder(t *testing.T) { bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB") require.Nil(t, err) defer assert.Nil(t, os.RemoveAll(bbDir)) - _, err = NewBatchBuilder(bbDir, synchDB, nil, 0, 32) + _, err = NewBatchBuilder(bbDir, synchDB, 0, 32) assert.Nil(t, err) } diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index 496be03..fbf8878 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -125,7 +125,7 @@ func newTestModules(t *testing.T) modules { batchBuilderDBPath, err = ioutil.TempDir("", "tmpBatchBuilderDB") require.NoError(t, err) deleteme = append(deleteme, batchBuilderDBPath) - batchBuilder, err := batchbuilder.NewBatchBuilder(batchBuilderDBPath, syncStateDB, nil, 0, uint64(nLevels)) + batchBuilder, err := batchbuilder.NewBatchBuilder(batchBuilderDBPath, syncStateDB, 0, uint64(nLevels)) assert.NoError(t, err) return modules{ diff --git a/coordinator/pipeline.go b/coordinator/pipeline.go index 60f6417..1431383 100644 --- a/coordinator/pipeline.go +++ b/coordinator/pipeline.go @@ -348,11 +348,10 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e // 4. Call BatchBuilder with TxSelector output configBatch := &batchbuilder.ConfigBatch{ - ForgerAddress: p.cfg.ForgerAddress, TxProcessorConfig: p.cfg.TxProcessorConfig, } zkInputs, err := p.batchBuilder.BuildBatch(coordIdxs, configBatch, l1UserTxsExtra, - l1CoordTxs, poolL2Txs, nil) + l1CoordTxs, poolL2Txs) if err != nil { return nil, tracerr.Wrap(err) } diff --git a/db/l2db/l2db_test.go b/db/l2db/l2db_test.go index 410a05c..bf49d11 100644 --- a/db/l2db/l2db_test.go +++ b/db/l2db/l2db_test.go @@ -131,7 +131,8 @@ func generatePoolL2Txs() ([]common.PoolL2Tx, error) { PoolTransfer(1) B-A: 8 (2) PoolTransfer(2) B-A: 1 (1) PoolTransfer(1) A-B: 3 (1) - PoolTransfer(2) B-A: 5 (2) + PoolTransferToEthAddr(2) B-A: 5 (2) + PoolTransferToBJJ(2) B-A: 5 (2) PoolExit(1) A: 5 (2) PoolExit(2) B: 3 (1) diff --git a/node/node.go b/node/node.go index 7bc8db7..1551a52 100644 --- a/node/node.go +++ b/node/node.go @@ -228,7 +228,7 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { return nil, tracerr.Wrap(err) } batchBuilder, err := batchbuilder.NewBatchBuilder(cfg.Coordinator.BatchBuilder.Path, - stateDB, nil, 0, uint64(cfg.Coordinator.Circuit.NLevels)) + stateDB, 0, uint64(cfg.Coordinator.Circuit.NLevels)) if err != nil { return nil, tracerr.Wrap(err) } diff --git a/test/zkproof/flows_test.go b/test/zkproof/flows_test.go new file mode 100644 index 0000000..17efd5c --- /dev/null +++ b/test/zkproof/flows_test.go @@ -0,0 +1,247 @@ +package zkproof + +import ( + "io/ioutil" + "os" + "strconv" + "testing" + "time" + + ethCommon "github.com/ethereum/go-ethereum/common" + ethCrypto "github.com/ethereum/go-ethereum/crypto" + "github.com/hermeznetwork/hermez-node/batchbuilder" + "github.com/hermeznetwork/hermez-node/common" + dbUtils "github.com/hermeznetwork/hermez-node/db" + "github.com/hermeznetwork/hermez-node/db/historydb" + "github.com/hermeznetwork/hermez-node/db/l2db" + "github.com/hermeznetwork/hermez-node/db/statedb" + "github.com/hermeznetwork/hermez-node/log" + "github.com/hermeznetwork/hermez-node/test" + "github.com/hermeznetwork/hermez-node/test/til" + "github.com/hermeznetwork/hermez-node/test/txsets" + "github.com/hermeznetwork/hermez-node/txselector" + "github.com/jmoiron/sqlx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func addTokens(t *testing.T, tc *til.Context, db *sqlx.DB) { + var tokens []common.Token + for i := 0; i < int(tc.LastRegisteredTokenID); i++ { + tokens = append(tokens, common.Token{ + TokenID: common.TokenID(i + 1), + EthBlockNum: 1, + EthAddr: ethCommon.BytesToAddress([]byte{byte(i + 1)}), + Name: strconv.Itoa(i), + Symbol: strconv.Itoa(i), + Decimals: 18, + }) + } + + hdb := historydb.NewHistoryDB(db) + assert.NoError(t, hdb.AddBlock(&common.Block{ + Num: 1, + })) + assert.NoError(t, hdb.AddTokens(tokens)) +} + +func addL2Txs(t *testing.T, l2DB *l2db.L2DB, poolL2Txs []common.PoolL2Tx) { + for i := 0; i < len(poolL2Txs); i++ { + err := l2DB.AddTxTest(&poolL2Txs[i]) + if err != nil { + log.Error(err) + } + require.NoError(t, err) + } +} + +func addAccCreationAuth(t *testing.T, tc *til.Context, l2DB *l2db.L2DB, chainID uint16, hermezContractAddr ethCommon.Address, username string) []byte { + user := tc.Users[username] + auth := &common.AccountCreationAuth{ + EthAddr: user.Addr, + BJJ: user.BJJ.Public().Compress(), + } + err := auth.Sign(func(hash []byte) ([]byte, error) { + return ethCrypto.Sign(hash, user.EthSk) + }, chainID, hermezContractAddr) + assert.NoError(t, err) + + err = l2DB.AddAccountCreationAuth(auth) + assert.NoError(t, err) + return auth.Signature +} + +func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, coordUser *til.User) (*txselector.TxSelector, *l2db.L2DB, *statedb.StateDB) { + pass := os.Getenv("POSTGRES_PASS") + db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez") + require.NoError(t, err) + l2DB := l2db.NewL2DB(db, 10, 100, 24*time.Hour) + + dir, err := ioutil.TempDir("", "tmpSyncDB") + require.NoError(t, err) + defer assert.NoError(t, os.RemoveAll(dir)) + syncStateDB, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 0) + require.NoError(t, err) + + txselDir, err := ioutil.TempDir("", "tmpTxSelDB") + require.NoError(t, err) + defer assert.NoError(t, os.RemoveAll(dir)) + + // use Til Coord keys for tests compatibility + coordAccount := &txselector.CoordAccount{ + Addr: coordUser.Addr, + BJJ: coordUser.BJJ.Public().Compress(), + AccountCreationAuth: nil, + } + auth := common.AccountCreationAuth{ + EthAddr: coordUser.Addr, + BJJ: coordUser.BJJ.Public().Compress(), + } + err = auth.Sign(func(hash []byte) ([]byte, error) { + return ethCrypto.Sign(hash, coordUser.EthSk) + }, chainID, hermezContractAddr) + assert.NoError(t, err) + coordAccount.AccountCreationAuth = auth.Signature + + txsel, err := txselector.NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB) + require.NoError(t, err) + + test.WipeDB(l2DB.DB()) + + return txsel, l2DB, syncStateDB +} + +func TestTxSelectorBatchBuilderZKInputs(t *testing.T) { + tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx) + // generate test transactions, the L1CoordinatorTxs generated by Til + // will be ignored at this test, as will be the TxSelector who + // generates them when needed + blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0) + require.NoError(t, err) + + hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6") + txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"]) + + bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB") + require.NoError(t, err) + bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels) + require.NoError(t, err) + + // restart nonces of TilContext, as will be set by generating directly + // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs + tc.RestartNonces() + + // 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, + } + + // loop over the first 6 batches + expectedRoots := []string{"0", "0", "13644148972047617726265275926674266298636745191961029124811988256139761111521", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "4191361650490017591061467288209836928064232431729236465872209988325272262963"} + for i := 0; i < 6; i++ { + log.Debugf("block:0 batch:%d", i+1) + var l1UserTxs []common.L1Tx + if blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum != nil { + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum]) + } + // TxSelector select the transactions for the next Batch + coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + require.NoError(t, err) + // BatchBuilder build Batch + zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) + require.NoError(t, err) + assert.Equal(t, expectedRoots[i], bb.LocalStateDB().MT.Root().BigInt().String()) + sendProofAndCheckResp(t, zki) + } + + log.Debug("block:0 batch:7") + // simulate the PoolL2Txs of the batch6 + batchPoolL2 := ` + Type: PoolL2 + PoolTransferToEthAddr(1) A-B: 200 (126) + PoolTransferToEthAddr(0) B-C: 100 (126)` + l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2) + require.NoError(t, err) + // add AccountCreationAuths that will be used at the next batch + _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "B") + _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "C") + addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB + l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum]) + // TxSelector select the transactions for the next Batch + coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + require.NoError(t, err) + // BatchBuilder build Batch + zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) + require.NoError(t, err) + assert.Equal(t, "7614010373759339299470010949167613050707822522530721724565424494781010548240", bb.LocalStateDB().MT.Root().BigInt().String()) + sendProofAndCheckResp(t, zki) + err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.LocalAccountsDB().CurrentBatch()) + require.NoError(t, err) + + log.Debug("block:0 batch:8") + // simulate the PoolL2Txs of the batch8 + batchPoolL2 = ` + Type: PoolL2 + PoolTransfer(0) A-B: 100 (126) + PoolTransfer(0) C-A: 50 (126) + PoolTransfer(1) B-C: 100 (126) + PoolExit(0) A: 100 (126)` + l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2) + require.NoError(t, err) + addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum]) + // TxSelector select the transactions for the next Batch + coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + require.NoError(t, err) + // BatchBuilder build Batch + zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) + require.NoError(t, err) + assert.Equal(t, "21231789250434471575486264439945776732824482207853465397552873521865656677689", bb.LocalStateDB().MT.Root().BigInt().String()) + sendProofAndCheckResp(t, zki) + err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch()) + require.NoError(t, err) + + log.Debug("(batch9) block:1 batch:1") + // simulate the PoolL2Txs of the batch9 + batchPoolL2 = ` + Type: PoolL2 + PoolTransfer(0) D-A: 300 (126) + PoolTransfer(0) B-D: 100 (126)` + l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2) + require.NoError(t, err) + addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum]) + // TxSelector select the transactions for the next Batch + coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + require.NoError(t, err) + // BatchBuilder build Batch + zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) + require.NoError(t, err) + assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String()) + sendProofAndCheckResp(t, zki) + err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch()) + require.NoError(t, err) + + log.Debug("(batch10) block:1 batch:2") + l2Txs = []common.PoolL2Tx{} + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum]) + // TxSelector select the transactions for the next Batch + coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs) + require.NoError(t, err) + // BatchBuilder build Batch + zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs) + require.NoError(t, err) + // same root as previous batch, as the L1CoordinatorTxs created by the + // Til set is not created by the TxSelector in this test + assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String()) + sendProofAndCheckResp(t, zki) + err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch()) + require.NoError(t, err) +} diff --git a/test/zkproof/zkproof_test.go b/test/zkproof/zkproof_test.go index d8745ed..4eea363 100644 --- a/test/zkproof/zkproof_test.go +++ b/test/zkproof/zkproof_test.go @@ -11,6 +11,7 @@ import ( "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/db/statedb" + "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/prover" "github.com/hermeznetwork/hermez-node/test/til" "github.com/hermeznetwork/hermez-node/test/txsets" @@ -26,9 +27,7 @@ const pollInterval = 200 * time.Millisecond func TestMain(m *testing.M) { exitVal := 0 proofServerURL = os.Getenv("PROOF_SERVER_URL") - if proofServerURL != "" { - exitVal = m.Run() - } + exitVal = m.Run() os.Exit(exitVal) } @@ -38,7 +37,7 @@ const MaxL1Tx = 256 const MaxFeeTx = 64 const ChainID uint16 = 1 -var config = txprocessor.Config{ +var txprocConfig = txprocessor.Config{ NLevels: uint32(NLevels), MaxTx: MaxTx, MaxL1Tx: MaxL1Tx, @@ -46,19 +45,24 @@ var config = txprocessor.Config{ ChainID: ChainID, } -func initStateDB(t *testing.T) *statedb.StateDB { +func initStateDB(t *testing.T, typ statedb.TypeStateDB) *statedb.StateDB { dir, err := ioutil.TempDir("", "tmpdb") require.NoError(t, err) defer assert.Nil(t, os.RemoveAll(dir)) - sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, NLevels) + sdb, err := statedb.NewStateDB(dir, 128, typ, NLevels) require.NoError(t, err) return sdb } -func sendProofAndCheckResp(t *testing.T, ptOut *txprocessor.ProcessTxOutput) { +func sendProofAndCheckResp(t *testing.T, zki *common.ZKInputs) { + if proofServerURL == "" { + log.Debug("No PROOF_SERVER_URL defined, not using ProofServer") + return + } + // Store zkinputs json for debugging purposes - zkInputsJSON, err := json.Marshal(ptOut.ZKInputs) + zkInputsJSON, err := json.Marshal(zki) require.NoError(t, err) err = ioutil.WriteFile("/tmp/dbgZKInputs.json", zkInputsJSON, 0640) //nolint:gosec require.NoError(t, err) @@ -66,7 +70,7 @@ func sendProofAndCheckResp(t *testing.T, ptOut *txprocessor.ProcessTxOutput) { proofServerClient := prover.NewProofServerClient(proofServerURL, pollInterval) err = proofServerClient.WaitReady(context.Background()) require.NoError(t, err) - err = proofServerClient.CalculateProof(context.Background(), ptOut.ZKInputs) + err = proofServerClient.CalculateProof(context.Background(), zki) require.NoError(t, err) proof, pubInputs, err := proofServerClient.GetProof(context.Background()) require.NoError(t, err) @@ -75,9 +79,9 @@ func sendProofAndCheckResp(t *testing.T, ptOut *txprocessor.ProcessTxOutput) { } func TestZKInputsEmpty(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) coordIdxs := []common.Idx{} l1UserTxs := []common.L1Tx{} @@ -86,7 +90,7 @@ func TestZKInputsEmpty(t *testing.T) { ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) // test empty batch ZKInputs + sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs = txsets.GenerateTxsZKInputs0(t, ChainID) @@ -99,79 +103,79 @@ func TestZKInputsEmpty(t *testing.T) { l2Txs = []common.PoolL2Tx{} ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) // test empty batch ZKInputs after a non-empty batch + sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs after a non-empty batch } func TestZKInputs0(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs0(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs1(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs1(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs2(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs2(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs3(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs3(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs4(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs4(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs5(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs5(t, ChainID) - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } func TestZKInputs6(t *testing.T) { - sdb := initStateDB(t) + sdb := initStateDB(t, statedb.TypeBatchBuilder) tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx) blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0) @@ -181,12 +185,12 @@ func TestZKInputs6(t *testing.T) { // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs tc.RestartNonces() - tp := txprocessor.NewTxProcessor(sdb, config) + tp := txprocessor.NewTxProcessor(sdb, txprocConfig) // batch1 ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch2 l1UserTxs := []common.L1Tx{} @@ -194,7 +198,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch3 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum]) @@ -202,7 +206,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch4 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum]) @@ -210,7 +214,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch5 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum]) @@ -218,7 +222,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch6 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum]) @@ -226,10 +230,10 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch7 - // simulate the PoolL2Txs of the batch6 + // simulate the PoolL2Txs of the batch7 batchPoolL2 := ` Type: PoolL2 PoolTransferToEthAddr(1) A-B: 200 (126) @@ -244,10 +248,10 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch8 - // simulate the PoolL2Txs of the batch7 + // simulate the PoolL2Txs of the batch8 batchPoolL2 = ` Type: PoolL2 PoolTransfer(0) A-B: 100 (126) @@ -262,7 +266,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch9 // simulate the PoolL2Txs of the batch9 @@ -279,7 +283,7 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) // batch10 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum]) @@ -288,5 +292,5 @@ func TestZKInputs6(t *testing.T) { ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs) require.NoError(t, err) - sendProofAndCheckResp(t, ptOut) + sendProofAndCheckResp(t, ptOut.ZKInputs) } diff --git a/txprocessor/zkinputsgen_test.go b/txprocessor/zkinputsgen_test.go index a3f06d4..1ca135b 100644 --- a/txprocessor/zkinputsgen_test.go +++ b/txprocessor/zkinputsgen_test.go @@ -674,7 +674,7 @@ func TestZKInputs6(t *testing.T) { } tp := NewTxProcessor(sdb, config) - tc := til.NewContext(0, common.RollupConstMaxL1UserTx) + tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx) blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0) require.NoError(t, err) diff --git a/txselector/txselector_test.go b/txselector/txselector_test.go index 9f1d443..b924e6a 100644 --- a/txselector/txselector_test.go +++ b/txselector/txselector_test.go @@ -1,10 +1,8 @@ package txselector import ( - "crypto/ecdsa" "fmt" "io/ioutil" - "math/big" "os" "strconv" "testing" @@ -22,13 +20,12 @@ import ( "github.com/hermeznetwork/hermez-node/test/til" "github.com/hermeznetwork/hermez-node/test/txsets" "github.com/hermeznetwork/hermez-node/txprocessor" - "github.com/iden3/go-iden3-crypto/babyjub" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, testSet string) (*TxSelector, *til.Context) { +func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, coordUser *til.User) *TxSelector { pass := os.Getenv("POSTGRES_PASS") db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez") require.NoError(t, err) @@ -37,45 +34,36 @@ func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address dir, err := ioutil.TempDir("", "tmpdb") require.NoError(t, err) defer assert.NoError(t, os.RemoveAll(dir)) - sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeTxSelector, 0) + syncStateDB, err := statedb.NewStateDB(dir, 128, statedb.TypeTxSelector, 0) require.NoError(t, err) txselDir, err := ioutil.TempDir("", "tmpTxSelDB") require.NoError(t, err) defer assert.NoError(t, os.RemoveAll(dir)) - // coordinator keys - var ethSk ecdsa.PrivateKey - ethSk.D = big.NewInt(int64(1)) // only for testing - ethSk.PublicKey.X, ethSk.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(ethSk.D.Bytes()) - ethSk.Curve = ethCrypto.S256() - addr := ethCrypto.PubkeyToAddress(ethSk.PublicKey) - var bjj babyjub.PublicKeyComp - err = bjj.UnmarshalText([]byte("c433f7a696b7aa3a5224efb3993baf0ccd9e92eecee0c29a3f6c8208a9e81d9e")) - require.NoError(t, err) + // use Til Coord keys for tests compatibility coordAccount := &CoordAccount{ - Addr: addr, - BJJ: bjj, + Addr: coordUser.Addr, + BJJ: coordUser.BJJ.Public().Compress(), AccountCreationAuth: nil, } + fmt.Printf("%v", coordAccount) auth := common.AccountCreationAuth{ - EthAddr: addr, - BJJ: bjj, + EthAddr: coordUser.Addr, + BJJ: coordUser.BJJ.Public().Compress(), } err = auth.Sign(func(hash []byte) ([]byte, error) { - return ethCrypto.Sign(hash, ðSk) + return ethCrypto.Sign(hash, coordUser.EthSk) }, chainID, hermezContractAddr) assert.NoError(t, err) coordAccount.AccountCreationAuth = auth.Signature - txsel, err := NewTxSelector(coordAccount, txselDir, sdb, l2DB) + txsel, err := NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB) require.NoError(t, err) test.WipeDB(txsel.l2db.DB()) - tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx) - - return txsel, tc + return txsel } func addAccCreationAuth(t *testing.T, tc *til.Context, txsel *TxSelector, chainID uint16, hermezContractAddr ethCommon.Address, username string) []byte { @@ -155,15 +143,16 @@ func checkSortedByNonce(t *testing.T, testAccNonces map[common.Idx]common.Nonce, func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { chainID := uint16(0) - hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6") - txsel, tc := initTest(t, chainID, hermezContractAddr, txsets.SetPool0) - + tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx) // generate test transactions, the L1CoordinatorTxs generated by Til // will be ignored at this test, as will be the TxSelector who // generates them when needed blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0) 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() @@ -262,21 +251,22 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { // simulate the PoolL2Txs of the batch7 batchPoolL2 := ` Type: PoolL2 - PoolTransfer(1) A-B: 200 (126) - PoolTransfer(0) B-C: 100 (126)` + PoolTransferToEthAddr(1) A-B: 200 (126) + PoolTransferToEthAddr(0) B-C: 100 (126)` poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2) require.NoError(t, err) // add AccountCreationAuths that will be used at the next batch accAuthSig0 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "B") accAuthSig1 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "C") - // add ToEthAddr for the corresponent ToIdx, and remove ToIdx for Batches[6].L2Tx - poolL2Txs[0].ToEthAddr = tc.Users["B"].Addr - poolL2Txs[0].ToIdx = common.Idx(0) - poolL2Txs[1].ToEthAddr = tc.Users["C"].Addr - poolL2Txs[1].ToIdx = common.Idx(0) // add the PoolL2Txs to the l2DB addL2Txs(t, txsel, poolL2Txs) - + // check signatures of L2Txs from the L2DB (to check that the + // parameters of the PoolL2Tx match the original parameters signed + // before inserting it to the L2DB) + l2TxsFromDB, err := txsel.l2db.GetPendingTxs() + require.NoError(t, err) + assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress())) + 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) require.NoError(t, err) @@ -314,6 +304,15 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2) require.NoError(t, err) addL2Txs(t, txsel, poolL2Txs) + // check signatures of L2Txs from the L2DB (to check that the + // parameters of the PoolL2Tx match the original parameters signed + // before inserting it to the L2DB) + l2TxsFromDB, err = txsel.l2db.GetPendingTxs() + require.NoError(t, err) + assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress())) + assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["C"].BJJ.Public().Compress())) + assert.True(t, l2TxsFromDB[2].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress())) + 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) require.NoError(t, err) @@ -348,6 +347,13 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) { poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2) require.NoError(t, err) addL2Txs(t, txsel, poolL2Txs) + // check signatures of L2Txs from the L2DB (to check that the + // parameters of the PoolL2Tx match the original parameters signed + // before inserting it to the L2DB) + l2TxsFromDB, err = txsel.l2db.GetPendingTxs() + require.NoError(t, err) + assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["D"].BJJ.Public().Compress())) + 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) require.NoError(t, err)