diff --git a/batchbuilder/batchbuilder.go b/batchbuilder/batchbuilder.go index 5d39209..3d917a6 100644 --- a/batchbuilder/batchbuilder.go +++ b/batchbuilder/batchbuilder.go @@ -63,3 +63,8 @@ func (bb *BatchBuilder) BuildBatch(coordIdxs []common.Idx, configBatch *ConfigBa ptOut, err := bb.localStateDB.ProcessTxs(ptc, coordIdxs, l1usertxs, l1coordinatortxs, pooll2txs) return ptOut.ZKInputs, tracerr.Wrap(err) } + +// LocalStateDB returns the underlying LocalStateDB +func (bb *BatchBuilder) LocalStateDB() *statedb.LocalStateDB { + return bb.localStateDB +} diff --git a/coordinator/batch.go b/coordinator/batch.go index 10c7561..ce94b4f 100644 --- a/coordinator/batch.go +++ b/coordinator/batch.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math/big" "path" "github.com/ethereum/go-ethereum/core/types" @@ -29,6 +30,7 @@ type BatchInfo struct { ServerProof prover.Client ZKInputs *common.ZKInputs Proof *prover.Proof + PublicInputs []*big.Int L1UserTxsExtra []common.L1Tx L1CoordTxs []common.L1Tx L2Txs []common.PoolL2Tx diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index 6f7befa..3729789 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -638,22 +638,14 @@ func (p *Pipeline) SetSyncStats(stats *synchronizer.Stats) { p.statsCh <- *stats } -// Start the forging pipeline -func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, - syncStats *synchronizer.Stats, initSCVars *synchronizer.SCVariables) error { - if p.started { - log.Fatal("Pipeline already started") - } - p.started = true - - // Reset pipeline state +// reset pipeline state +func (p *Pipeline) reset(batchNum common.BatchNum, lastForgeL1TxsNum int64, + initSCVars *synchronizer.SCVariables) error { p.batchNum = batchNum p.lastForgeL1TxsNum = lastForgeL1TxsNum p.vars = *initSCVars p.lastScheduledL1BatchBlockNum = 0 - p.ctx, p.cancel = context.WithCancel(context.Background()) - err := p.txSelector.Reset(p.batchNum) if err != nil { return tracerr.Wrap(err) @@ -662,6 +654,21 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, if err != nil { return tracerr.Wrap(err) } + return nil +} + +// Start the forging pipeline +func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, + syncStats *synchronizer.Stats, initSCVars *synchronizer.SCVariables) error { + if p.started { + log.Fatal("Pipeline already started") + } + p.started = true + + if err := p.reset(batchNum, lastForgeL1TxsNum, initSCVars); err != nil { + return tracerr.Wrap(err) + } + p.ctx, p.cancel = context.WithCancel(context.Background()) queueSize := 1 batchChSentServerProof := make(chan *BatchInfo, queueSize) @@ -840,13 +847,14 @@ func (p *Pipeline) forgeSendServerProof(ctx context.Context, batchNum common.Bat // waitServerProof gets the generated zkProof & sends it to the SmartContract func (p *Pipeline) waitServerProof(ctx context.Context, batchInfo *BatchInfo) error { - proof, err := batchInfo.ServerProof.GetProof(ctx) // blocking call, until not resolved don't continue. Returns when the proof server has calculated the proof + proof, pubInputs, err := batchInfo.ServerProof.GetProof(ctx) // blocking call, until not resolved don't continue. Returns when the proof server has calculated the proof if err != nil { return tracerr.Wrap(err) } p.proversPool.Add(batchInfo.ServerProof) batchInfo.ServerProof = nil batchInfo.Proof = proof + batchInfo.PublicInputs = pubInputs batchInfo.ForgeBatchArgs = p.prepareForgeBatchArgs(batchInfo) batchInfo.TxStatus = TxStatusPending p.cfg.debugBatchStore(batchInfo) diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index c5d4fd0..8cee0f4 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -11,14 +11,17 @@ import ( ethCommon "github.com/ethereum/go-ethereum/common" "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/eth" "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/prover" "github.com/hermeznetwork/hermez-node/synchronizer" "github.com/hermeznetwork/hermez-node/test" + "github.com/hermeznetwork/hermez-node/test/til" "github.com/hermeznetwork/hermez-node/txselector" "github.com/hermeznetwork/tracerr" "github.com/iden3/go-merkletree/db/pebble" @@ -73,15 +76,29 @@ var syncDBPath string var txSelDBPath string var batchBuilderDBPath string -func newTestModules(t *testing.T) (*historydb.HistoryDB, *l2db.L2DB, - *txselector.TxSelector, *batchbuilder.BatchBuilder) { // FUTURE once Synchronizer is ready, should return it also +type modules struct { + historyDB *historydb.HistoryDB + l2DB *l2db.L2DB + txSelector *txselector.TxSelector + batchBuilder *batchbuilder.BatchBuilder + stateDB *statedb.StateDB +} + +var maxL1UserTxs uint64 = 128 +var maxL1Txs uint64 = 256 +var maxL1CoordinatorTxs uint64 = maxL1Txs - maxL1UserTxs +var maxTxs uint64 = 376 +var nLevels uint32 = 32 //nolint:deadcode,unused +var maxFeeTxs uint32 = 64 //nolint:deadcode,varcheck + +func newTestModules(t *testing.T) modules { nLevels := 32 var err error syncDBPath, err = ioutil.TempDir("", "tmpSyncDB") require.NoError(t, err) deleteme = append(deleteme, syncDBPath) - syncSdb, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, nLevels) + syncStateDB, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, nLevels) assert.NoError(t, err) pass := os.Getenv("POSTGRES_PASS") @@ -94,18 +111,22 @@ func newTestModules(t *testing.T) (*historydb.HistoryDB, *l2db.L2DB, txSelDBPath, err = ioutil.TempDir("", "tmpTxSelDB") require.NoError(t, err) deleteme = append(deleteme, txSelDBPath) - txsel, err := txselector.NewTxSelector(txSelDBPath, syncSdb, l2DB, 10, 10, 10) + txSelector, err := txselector.NewTxSelector(txSelDBPath, syncStateDB, l2DB, maxL1UserTxs, maxL1CoordinatorTxs, maxTxs) assert.NoError(t, err) batchBuilderDBPath, err = ioutil.TempDir("", "tmpBatchBuilderDB") require.NoError(t, err) deleteme = append(deleteme, batchBuilderDBPath) - bb, err := batchbuilder.NewBatchBuilder(batchBuilderDBPath, syncSdb, nil, 0, uint64(nLevels)) + batchBuilder, err := batchbuilder.NewBatchBuilder(batchBuilderDBPath, syncStateDB, nil, 0, uint64(nLevels)) assert.NoError(t, err) - // l1Txs, coordinatorL1Txs, poolL2Txs := test.GenerateTestTxsFromSet(t, test.SetTest0) - - return historyDB, l2DB, txsel, bb + return modules{ + historyDB: historyDB, + l2DB: l2DB, + txSelector: txSelector, + batchBuilder: batchBuilder, + stateDB: syncStateDB, + } } type timer struct { @@ -121,9 +142,8 @@ func (t *timer) Time() int64 { var bidder = ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f") var forger = ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6") -func newTestCoordinator(t *testing.T, forgerAddr ethCommon.Address, ethClient *test.Client, ethClientSetup *test.ClientSetup) *Coordinator { - historyDB, l2DB, txsel, bb := newTestModules(t) - +func newTestCoordinator(t *testing.T, forgerAddr ethCommon.Address, ethClient *test.Client, + ethClientSetup *test.ClientSetup, modules modules) *Coordinator { debugBatchPath, err := ioutil.TempDir("", "tmpDebugBatch") require.NoError(t, err) deleteme = append(deleteme, debugBatchPath) @@ -149,12 +169,38 @@ func newTestCoordinator(t *testing.T, forgerAddr ethCommon.Address, ethClient *t Auction: *ethClientSetup.AuctionVariables, WDelayer: *ethClientSetup.WDelayerVariables, } - coord, err := NewCoordinator(conf, historyDB, l2DB, txsel, bb, serverProofs, - ethClient, scConsts, initSCVars) + coord, err := NewCoordinator(conf, modules.historyDB, modules.l2DB, modules.txSelector, + modules.batchBuilder, serverProofs, ethClient, scConsts, initSCVars) require.NoError(t, err) return coord } +func newTestSynchronizer(t *testing.T, ethClient *test.Client, ethClientSetup *test.ClientSetup, + modules modules) *synchronizer.Synchronizer { + sync, err := synchronizer.NewSynchronizer(ethClient, modules.historyDB, modules.stateDB, + synchronizer.Config{ + StartBlockNum: synchronizer.ConfigStartBlockNum{ + Rollup: 1, + Auction: 1, + WDelayer: 1, + }, + InitialVariables: synchronizer.SCVariables{ + Rollup: *ethClientSetup.RollupVariables, + Auction: *ethClientSetup.AuctionVariables, + WDelayer: *ethClientSetup.WDelayerVariables, + }, + }) + require.NoError(t, err) + return sync +} + +// TestCoordinatorFlow is a test where the coordinator is stared (which means +// that goroutines are spawned), and ethereum blocks are mined via the +// test.Client to simulate starting and stopping forging times. This test +// works without a synchronizer, and no l2txs are inserted in the pool, so all +// the batches are forged empty. The purpose of this test is to manually +// observe via the logs that nothing crashes and that the coordinator starts +// and stops forging at the right blocks. func TestCoordinatorFlow(t *testing.T) { if os.Getenv("TEST_COORD_FLOW") == "" { return @@ -162,7 +208,8 @@ func TestCoordinatorFlow(t *testing.T) { ethClientSetup := test.NewClientSetupExample() var timer timer ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) - coord := newTestCoordinator(t, forger, ethClient, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) // Bid for slot 2 and 4 _, err := ethClient.AuctionSetCoordinator(forger, "https://foo.bar") @@ -242,7 +289,8 @@ func TestCoordinatorStartStop(t *testing.T) { ethClientSetup := test.NewClientSetupExample() var timer timer ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) - coord := newTestCoordinator(t, forger, ethClient, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) coord.Start() coord.Stop() } @@ -253,13 +301,15 @@ func TestCoordCanForge(t *testing.T) { var timer timer ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) - coord := newTestCoordinator(t, forger, ethClient, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) _, err := ethClient.AuctionSetCoordinator(forger, "https://foo.bar") require.NoError(t, err) _, err = ethClient.AuctionBidSimple(2, big.NewInt(9999)) require.NoError(t, err) - bootCoord := newTestCoordinator(t, bootForger, ethClient, ethClientSetup) + modules2 := newTestModules(t) + bootCoord := newTestCoordinator(t, bootForger, ethClient, ethClientSetup, modules2) assert.Equal(t, forger, coord.cfg.ForgerAddress) assert.Equal(t, bootForger, bootCoord.cfg.ForgerAddress) @@ -293,13 +343,14 @@ func TestCoordCanForge(t *testing.T) { assert.Equal(t, false, bootCoord.canForge(&stats)) } -func TestCoordHandleMsgSyncStats(t *testing.T) { +func TestCoordHandleMsgSyncBlock(t *testing.T) { ethClientSetup := test.NewClientSetupExample() bootForger := ethClientSetup.AuctionVariables.BootCoordinator var timer timer ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) - coord := newTestCoordinator(t, forger, ethClient, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) _, err := ethClient.AuctionSetCoordinator(forger, "https://foo.bar") require.NoError(t, err) _, err = ethClient.AuctionBidSimple(2, big.NewInt(9999)) @@ -355,7 +406,8 @@ func TestPipelineShouldL1L2Batch(t *testing.T) { var timer timer ctx := context.Background() ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) - coord := newTestCoordinator(t, forger, ethClient, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) pipeline, err := coord.newPipeline(ctx) require.NoError(t, err) pipeline.vars = coord.vars @@ -414,6 +466,153 @@ func TestPipelineShouldL1L2Batch(t *testing.T) { assert.Equal(t, true, pipeline.shouldL1L2Batch()) } +// ethAddTokens adds the tokens from the blocks to the blockchain +func ethAddTokens(blocks []common.BlockData, client *test.Client) { + for _, block := range blocks { + for _, token := range block.Rollup.AddedTokens { + consts := eth.ERC20Consts{ + Name: fmt.Sprintf("Token %d", token.TokenID), + Symbol: fmt.Sprintf("TK%d", token.TokenID), + Decimals: 18, + } + // tokenConsts[token.TokenID] = consts + client.CtlAddERC20(token.EthAddr, consts) + } + } +} + +const testTokensLen = 3 +const testUsersLen = 4 + +func preloadSync(t *testing.T, ethClient *test.Client, sync *synchronizer.Synchronizer, + historyDB *historydb.HistoryDB, stateDB *statedb.StateDB) *til.Context { + // Create a set with `testTokensLen` tokens and for each token + // `testUsersLen` accounts. + var set []til.Instruction + // set = append(set, til.Instruction{Typ: "Blockchain"}) + for tokenID := 1; tokenID < testTokensLen; tokenID++ { + set = append(set, til.Instruction{ + Typ: til.TypeAddToken, + TokenID: common.TokenID(tokenID), + }) + } + depositAmount, ok := new(big.Int).SetString("10225000000000000000000000000000000", 10) + require.True(t, ok) + for tokenID := 0; tokenID < testTokensLen; tokenID++ { + for user := 0; user < testUsersLen; user++ { + set = append(set, til.Instruction{ + Typ: common.TxTypeCreateAccountDeposit, + TokenID: common.TokenID(tokenID), + DepositAmount: depositAmount, + From: fmt.Sprintf("User%d", user), + }) + } + } + set = append(set, til.Instruction{Typ: til.TypeNewBatchL1}) + set = append(set, til.Instruction{Typ: til.TypeNewBatchL1}) + set = append(set, til.Instruction{Typ: til.TypeNewBlock}) + + tc := til.NewContext(common.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocksFromInstructions(set) + require.NoError(t, err) + require.NotNil(t, blocks) + + ethAddTokens(blocks, ethClient) + err = ethClient.CtlAddBlocks(blocks) + require.NoError(t, err) + + ctx := context.Background() + for { + syncBlock, discards, err := sync.Sync2(ctx, nil) + require.NoError(t, err) + require.Nil(t, discards) + if syncBlock == nil { + break + } + } + dbTokens, err := historyDB.GetAllTokens() + require.Nil(t, err) + require.Equal(t, testTokensLen, len(dbTokens)) + + dbAccounts, err := historyDB.GetAllAccounts() + require.Nil(t, err) + require.Equal(t, testTokensLen*testUsersLen, len(dbAccounts)) + + sdbAccounts, err := stateDB.GetAccounts() + require.Nil(t, err) + require.Equal(t, testTokensLen*testUsersLen, len(sdbAccounts)) + + return tc +} + +func TestPipeline1(t *testing.T) { + ethClientSetup := test.NewClientSetupExample() + + var timer timer + ctx := context.Background() + ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) + modules := newTestModules(t) + coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) + sync := newTestSynchronizer(t, ethClient, ethClientSetup, modules) + pipeline, err := coord.newPipeline(ctx) + require.NoError(t, err) + + require.NotNil(t, sync) + require.NotNil(t, pipeline) + + // preload the synchronier (via the test ethClient) some tokens and + // users with positive balances + tilCtx := preloadSync(t, ethClient, sync, modules.historyDB, modules.stateDB) + syncStats := sync.Stats() + batchNum := common.BatchNum(syncStats.Sync.LastBatch) + syncSCVars := sync.SCVars() + + // Insert some l2txs in the Pool + setPool := ` +Type: PoolL2 + +PoolTransfer(0) User0-User1: 100 (126) +PoolTransfer(0) User1-User2: 200 (126) +PoolTransfer(0) User2-User3: 300 (126) + ` + l2txs, err := tilCtx.GeneratePoolL2Txs(setPool) + require.NoError(t, err) + for _, tx := range l2txs { + err := modules.l2DB.AddTxTest(&tx) //nolint:gosec + require.NoError(t, err) + } + + err = pipeline.reset(batchNum, syncStats.Sync.LastForgeL1TxsNum, &synchronizer.SCVariables{ + Rollup: *syncSCVars.Rollup, + Auction: *syncSCVars.Auction, + WDelayer: *syncSCVars.WDelayer, + }) + require.NoError(t, err) + // Sanity check + sdbAccounts, err := pipeline.txSelector.LocalAccountsDB().GetAccounts() + require.Nil(t, err) + require.Equal(t, testTokensLen*testUsersLen, len(sdbAccounts)) + + // Sanity check + sdbAccounts, err = pipeline.batchBuilder.LocalStateDB().GetAccounts() + require.Nil(t, err) + require.Equal(t, testTokensLen*testUsersLen, len(sdbAccounts)) + + // Sanity check + require.Equal(t, modules.stateDB.MerkleTree().Root(), + pipeline.batchBuilder.LocalStateDB().MerkleTree().Root()) + + batchNum++ + batchInfo, err := pipeline.forgeSendServerProof(ctx, batchNum) + require.NoError(t, err) + assert.Equal(t, 3, len(batchInfo.L2Txs)) + + batchNum++ + batchInfo, err = pipeline.forgeSendServerProof(ctx, batchNum) + require.NoError(t, err) + assert.Equal(t, 0, len(batchInfo.L2Txs)) +} + // TODO: Test Reorg // TODO: Test Pipeline // TODO: Test TxMonitor diff --git a/coordinator/purger.go b/coordinator/purger.go index 2202c90..852060f 100644 --- a/coordinator/purger.go +++ b/coordinator/purger.go @@ -143,8 +143,11 @@ func poolMarkInvalidOldNonces(l2DB *l2db.L2DB, stateDB *statedb.LocalStateDB, return tracerr.Wrap(err) } else if idx <= lastIdx { return tracerr.Wrap(fmt.Errorf("account with idx %v not found: %w", idx, err)) + } else { + return tracerr.Wrap(fmt.Errorf("unexpected stateDB error with idx %v: %w", idx, err)) } } + fmt.Printf("DBG acc: %#v\n", acc) idxsNonce[i].Idx = idx idxsNonce[i].Nonce = acc.Nonce } diff --git a/db/statedb/statedb.go b/db/statedb/statedb.go index 21d1c28..47aa799 100644 --- a/db/statedb/statedb.go +++ b/db/statedb/statedb.go @@ -486,7 +486,8 @@ func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common } if mt != nil { - return mt.Update(idx.BigInt(), v) + proof, err := mt.Update(idx.BigInt(), v) + return proof, tracerr.Wrap(err) } return nil, nil } @@ -504,6 +505,11 @@ func (s *StateDB) MTGetRoot() *big.Int { return s.mt.Root().BigInt() } +// MerkleTree returns the underlying StateDB merkle tree. It can be nil. +func (s *StateDB) MerkleTree() *merkletree.MerkleTree { + return s.mt +} + // LocalStateDB represents the local StateDB which allows to make copies from // the synchronizer StateDB, and is used by the tx-selector and the // batch-builder. LocalStateDB is an in-memory storage. diff --git a/go.mod b/go.mod index be2ca86..c52e522 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gobuffalo/packr/v2 v2.8.0 github.com/hermeznetwork/tracerr v0.3.1-0.20201126162137-de9930d0cf29 github.com/iden3/go-iden3-crypto v0.0.6-0.20201203095229-821a601d2002 - github.com/iden3/go-merkletree v0.0.0-20201203095330-4a8397a45644 + github.com/iden3/go-merkletree v0.0.0-20201215142017-730707e5659a github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee github.com/joho/godotenv v1.3.0 diff --git a/go.sum b/go.sum index 2373e5f..8827691 100644 --- a/go.sum +++ b/go.sum @@ -331,6 +331,8 @@ github.com/iden3/go-merkletree v0.0.0-20201103115630-ad30c8309b44 h1:d6AbzJWWUos github.com/iden3/go-merkletree v0.0.0-20201103115630-ad30c8309b44/go.mod h1:MRe6i0mi2oDVUzgBIHsNRE6XAg8EBuqIQZMsd+do+dU= github.com/iden3/go-merkletree v0.0.0-20201203095330-4a8397a45644 h1:obSehuklDMDpmQ4j0d6RxU70bjRjEWlGlkO13CKp8Fw= github.com/iden3/go-merkletree v0.0.0-20201203095330-4a8397a45644/go.mod h1:MRe6i0mi2oDVUzgBIHsNRE6XAg8EBuqIQZMsd+do+dU= +github.com/iden3/go-merkletree v0.0.0-20201215142017-730707e5659a h1:Wq5haqbfI0Ruht6nHotf+0HS5xAXKO17Xa6NBZVtTrM= +github.com/iden3/go-merkletree v0.0.0-20201215142017-730707e5659a/go.mod h1:MRe6i0mi2oDVUzgBIHsNRE6XAg8EBuqIQZMsd+do+dU= github.com/iden3/go-wasm3 v0.0.1/go.mod h1:j+TcAB94Dfrjlu5kJt83h2OqAU+oyNUTwNZnQyII1sI= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= diff --git a/prover/prover.go b/prover/prover.go index 91abd87..e360f86 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -63,7 +63,7 @@ type Client interface { // Non-blocking CalculateProof(ctx context.Context, zkInputs *common.ZKInputs) error // Blocking - GetProof(ctx context.Context) (*Proof, error) + GetProof(ctx context.Context) (*Proof, []*big.Int, error) // Non-Blocking Cancel(ctx context.Context) error // Blocking @@ -209,23 +209,23 @@ func (p *ProofServerClient) CalculateProof(ctx context.Context, zkInputs *common // GetProof retreives the Proof from the ServerProof, blocking until the proof // is ready. -func (p *ProofServerClient) GetProof(ctx context.Context) (*Proof, error) { +func (p *ProofServerClient) GetProof(ctx context.Context) (*Proof, []*big.Int, error) { if err := p.WaitReady(ctx); err != nil { - return nil, err + return nil, nil, err } status, err := p.apiStatus(ctx) if err != nil { - return nil, tracerr.Wrap(err) + return nil, nil, tracerr.Wrap(err) } if status.Status == StatusCodeSuccess { var proof Proof err := json.Unmarshal([]byte(status.Proof), &proof) if err != nil { - return nil, tracerr.Wrap(err) + return nil, nil, tracerr.Wrap(err) } - return &proof, nil + return &proof, nil, nil } - return nil, fmt.Errorf("status != StatusCodeSuccess, status = %v", status.Status) + return nil, nil, fmt.Errorf("status != StatusCodeSuccess, status = %v", status.Status) } // Cancel cancels any current proof computation @@ -265,13 +265,13 @@ func (p *MockClient) CalculateProof(ctx context.Context, zkInputs *common.ZKInpu } // GetProof retreives the Proof from the ServerProof -func (p *MockClient) GetProof(ctx context.Context) (*Proof, error) { +func (p *MockClient) GetProof(ctx context.Context) (*Proof, []*big.Int, error) { // Simulate a delay select { case <-time.After(500 * time.Millisecond): //nolint:gomnd - return &Proof{}, nil + return &Proof{}, nil, nil case <-ctx.Done(): - return nil, tracerr.Wrap(common.ErrDone) + return nil, nil, tracerr.Wrap(common.ErrDone) } } diff --git a/prover/prover_test.go b/prover/prover_test.go index 77378c6..a3eb7e0 100644 --- a/prover/prover_test.go +++ b/prover/prover_test.go @@ -53,7 +53,7 @@ func testCalculateProof(t *testing.T) { } func testGetProof(t *testing.T) { - proof, err := proofServerClient.GetProof(context.Background()) + proof, _, err := proofServerClient.GetProof(context.Background()) require.NoError(t, err) require.NotNil(t, proof) require.NotNil(t, proof.PiA) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index b01a0b7..1d99698 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -270,44 +270,6 @@ func ethAddTokens(blocks []common.BlockData, client *test.Client) { } } -// ethAddBlocks adds block data to the smart contracts -func ethAddBlocks(t *testing.T, blocks []common.BlockData, - client *test.Client, clientSetup *test.ClientSetup) { - for _, block := range blocks { - for _, token := range block.Rollup.AddedTokens { - _, err := client.RollupAddTokenSimple(token.EthAddr, clientSetup.RollupVariables.FeeAddToken) - require.Nil(t, err) - } - for _, tx := range block.Rollup.L1UserTxs { - client.CtlSetAddr(tx.FromEthAddr) - _, err := client.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.DepositAmount, tx.Amount, - uint32(tx.TokenID), int64(tx.ToIdx)) - require.Nil(t, err) - } - client.CtlSetAddr(clientSetup.AuctionVariables.BootCoordinator) - for _, batch := range block.Rollup.Batches { - _, err := client.RollupForgeBatch(ð.RollupForgeBatchArgs{ - NewLastIdx: batch.Batch.LastIdx, - NewStRoot: batch.Batch.StateRoot, - NewExitRoot: batch.Batch.ExitRoot, - L1CoordinatorTxs: batch.L1CoordinatorTxs, - L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty - L2TxsData: batch.L2Txs, - FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator, - // Circuit selector - VerifierIdx: 0, // Intentionally empty - L1Batch: batch.L1Batch, - ProofA: [2]*big.Int{}, // Intentionally empty - ProofB: [2][2]*big.Int{}, // Intentionally empty - ProofC: [2]*big.Int{}, // Intentionally empty - }) - require.Nil(t, err) - } - // Mine block and sync - client.CtlMineBlock() - } -} - func TestSync(t *testing.T) { // // Setup @@ -320,7 +282,7 @@ func TestSync(t *testing.T) { defer assert.Nil(t, os.RemoveAll(dir)) stateDB, err := statedb.NewStateDB(dir, statedb.TypeSynchronizer, 32) - assert.NoError(t, err) + require.NoError(t, err) // Init History DB pass := os.Getenv("POSTGRES_PASS") @@ -452,13 +414,14 @@ func TestSync(t *testing.T) { ethAddTokens(blocks, client) err = tc.FillBlocksExtra(blocks, &tilCfgExtra) - assert.NoError(t, err) + require.NoError(t, err) tc.FillBlocksL1UserTxsBatchNum(blocks) err = tc.FillBlocksForgedL1UserTxs(blocks) - assert.NoError(t, err) + require.NoError(t, err) // Add block data to the smart contracts - ethAddBlocks(t, blocks, client, clientSetup) + err = client.CtlAddBlocks(blocks) + require.NoError(t, err) // // Sync to synchronize the current state from the test smart contracts, @@ -629,11 +592,12 @@ func TestSync(t *testing.T) { ethAddTokens(blocks, client) err = tc.FillBlocksExtra(blocks, &tilCfgExtra) - assert.NoError(t, err) + require.NoError(t, err) tc.FillBlocksL1UserTxsBatchNum(blocks) // Add block data to the smart contracts - ethAddBlocks(t, blocks, client, clientSetup) + err = client.CtlAddBlocks(blocks) + require.NoError(t, err) // First sync detects the reorg and discards 4 blocks syncBlock, discards, err = s.Sync2(ctx, nil) diff --git a/test/ethclient.go b/test/ethclient.go index 5aec79e..a334acb 100644 --- a/test/ethclient.go +++ b/test/ethclient.go @@ -1719,3 +1719,50 @@ func (c *Client) WDelayerConstants() (*common.WDelayerConstants, error) { return c.wDelayerConstants, nil } + +// CtlAddBlocks adds block data to the smarts contracts. The added blocks will +// appear as mined. Not thread safe. +func (c *Client) CtlAddBlocks(blocks []common.BlockData) (err error) { + // NOTE: We don't lock because internally we call public functions that + // lock already. + for _, block := range blocks { + nextBlock := c.nextBlock() + rollup := nextBlock.Rollup + auction := nextBlock.Auction + for _, token := range block.Rollup.AddedTokens { + if _, err := c.RollupAddTokenSimple(token.EthAddr, rollup.Vars.FeeAddToken); err != nil { + return err + } + } + for _, tx := range block.Rollup.L1UserTxs { + c.CtlSetAddr(tx.FromEthAddr) + if _, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.DepositAmount, tx.Amount, + uint32(tx.TokenID), int64(tx.ToIdx)); err != nil { + return err + } + } + c.CtlSetAddr(auction.Vars.BootCoordinator) + for _, batch := range block.Rollup.Batches { + if _, err := c.RollupForgeBatch(ð.RollupForgeBatchArgs{ + NewLastIdx: batch.Batch.LastIdx, + NewStRoot: batch.Batch.StateRoot, + NewExitRoot: batch.Batch.ExitRoot, + L1CoordinatorTxs: batch.L1CoordinatorTxs, + L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty + L2TxsData: batch.L2Txs, + FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator, + // Circuit selector + VerifierIdx: 0, // Intentionally empty + L1Batch: batch.L1Batch, + ProofA: [2]*big.Int{}, // Intentionally empty + ProofB: [2][2]*big.Int{}, // Intentionally empty + ProofC: [2]*big.Int{}, // Intentionally empty + }); err != nil { + return err + } + } + // Mine block and sync + c.CtlMineBlock() + } + return nil +}