arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/test/zkproof/flows_test.go
test/zkproof/flows_test.goRaw
  1package zkproof
  2
  3import (
  4	"io/ioutil"
  5	"os"
  6	"strconv"
  7	"testing"
  8	"time"
  9
 10	ethCommon "github.com/ethereum/go-ethereum/common"
 11	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 12	"github.com/hermeznetwork/hermez-node/batchbuilder"
 13	"github.com/hermeznetwork/hermez-node/common"
 14	dbUtils "github.com/hermeznetwork/hermez-node/db"
 15	"github.com/hermeznetwork/hermez-node/db/historydb"
 16	"github.com/hermeznetwork/hermez-node/db/l2db"
 17	"github.com/hermeznetwork/hermez-node/db/statedb"
 18	"github.com/hermeznetwork/hermez-node/log"
 19	"github.com/hermeznetwork/hermez-node/test"
 20	"github.com/hermeznetwork/hermez-node/test/til"
 21	"github.com/hermeznetwork/hermez-node/test/txsets"
 22	"github.com/hermeznetwork/hermez-node/txselector"
 23	"github.com/jmoiron/sqlx"
 24	"github.com/stretchr/testify/assert"
 25	"github.com/stretchr/testify/require"
 26)
 27
 28func addTokens(t *testing.T, tc *til.Context, db *sqlx.DB) {
 29	var tokens []common.Token
 30	for i := 0; i < int(tc.LastRegisteredTokenID); i++ {
 31		tokens = append(tokens, common.Token{
 32			TokenID:     common.TokenID(i + 1),
 33			EthBlockNum: 1,
 34			EthAddr:     ethCommon.BytesToAddress([]byte{byte(i + 1)}),
 35			Name:        strconv.Itoa(i),
 36			Symbol:      strconv.Itoa(i),
 37			Decimals:    18,
 38		})
 39	}
 40
 41	hdb := historydb.NewHistoryDB(db, db, nil)
 42	assert.NoError(t, hdb.AddBlock(&common.Block{
 43		Num: 1,
 44	}))
 45	assert.NoError(t, hdb.AddTokens(tokens))
 46}
 47
 48func addL2Txs(t *testing.T, l2DB *l2db.L2DB, poolL2Txs []common.PoolL2Tx) {
 49	for i := 0; i < len(poolL2Txs); i++ {
 50		err := l2DB.AddTxTest(&poolL2Txs[i])
 51		if err != nil {
 52			log.Error(err)
 53		}
 54		require.NoError(t, err)
 55	}
 56}
 57
 58func addAccCreationAuth(t *testing.T, tc *til.Context, l2DB *l2db.L2DB, chainID uint16, hermezContractAddr ethCommon.Address, username string) []byte {
 59	user := tc.Users[username]
 60	auth := &common.AccountCreationAuth{
 61		EthAddr: user.Addr,
 62		BJJ:     user.BJJ.Public().Compress(),
 63	}
 64	err := auth.Sign(func(hash []byte) ([]byte, error) {
 65		return ethCrypto.Sign(hash, user.EthSk)
 66	}, chainID, hermezContractAddr)
 67	assert.NoError(t, err)
 68
 69	err = l2DB.AddAccountCreationAuth(auth)
 70	assert.NoError(t, err)
 71	return auth.Signature
 72}
 73
 74func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, coordUser *til.User) (*txselector.TxSelector, *l2db.L2DB, *statedb.StateDB) {
 75	pass := os.Getenv("POSTGRES_PASS")
 76	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 77	require.NoError(t, err)
 78	l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
 79
 80	dir, err := ioutil.TempDir("", "tmpSyncDB")
 81	require.NoError(t, err)
 82	defer assert.NoError(t, os.RemoveAll(dir))
 83	syncStateDB, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 84		Type: statedb.TypeSynchronizer, NLevels: 0})
 85	require.NoError(t, err)
 86
 87	txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
 88	require.NoError(t, err)
 89	defer assert.NoError(t, os.RemoveAll(dir))
 90
 91	// use Til Coord keys for tests compatibility
 92	coordAccount := &txselector.CoordAccount{
 93		Addr:                coordUser.Addr,
 94		BJJ:                 coordUser.BJJ.Public().Compress(),
 95		AccountCreationAuth: nil,
 96	}
 97	auth := common.AccountCreationAuth{
 98		EthAddr: coordUser.Addr,
 99		BJJ:     coordUser.BJJ.Public().Compress(),
100	}
101	err = auth.Sign(func(hash []byte) ([]byte, error) {
102		return ethCrypto.Sign(hash, coordUser.EthSk)
103	}, chainID, hermezContractAddr)
104	assert.NoError(t, err)
105	coordAccount.AccountCreationAuth = auth.Signature
106
107	txsel, err := txselector.NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
108	require.NoError(t, err)
109
110	test.WipeDB(l2DB.DB())
111
112	return txsel, l2DB, syncStateDB
113}
114
115func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) {
116	tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
117	// generate test transactions, the L1CoordinatorTxs generated by Til
118	// will be ignored at this test, as will be the TxSelector who
119	// generates them when needed
120	blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
121	require.NoError(t, err)
122
123	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
124	txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
125
126	bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
127	require.NoError(t, err)
128	bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
129	require.NoError(t, err)
130
131	// restart nonces of TilContext, as will be set by generating directly
132	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
133	tc.RestartNonces()
134
135	// add tokens to HistoryDB to avoid breaking FK constrains
136	addTokens(t, tc, l2DBTxSel.DB())
137
138	selectionConfig := &txselector.SelectionConfig{
139		MaxL1UserTxs:      100, // TODO
140		TxProcessorConfig: txprocConfig,
141	}
142	configBatch := &batchbuilder.ConfigBatch{
143		// ForgerAddress:
144		TxProcessorConfig: txprocConfig,
145	}
146
147	// loop over the first 6 batches
148	expectedRoots := []string{"0", "0", "13644148972047617726265275926674266298636745191961029124811988256139761111521", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "4191361650490017591061467288209836928064232431729236465872209988325272262963"}
149	for i := 0; i < 6; i++ {
150		log.Debugf("block:0 batch:%d", i+1)
151		var l1UserTxs []common.L1Tx
152		if blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum != nil {
153			l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum])
154		}
155		// TxSelector select the transactions for the next Batch
156		coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
157		require.NoError(t, err)
158		// BatchBuilder build Batch
159		zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
160		require.NoError(t, err)
161		assert.Equal(t, expectedRoots[i], bb.LocalStateDB().MT.Root().BigInt().String())
162		sendProofAndCheckResp(t, zki)
163	}
164
165	log.Debug("block:0 batch:7")
166	// simulate the PoolL2Txs of the batch6
167	batchPoolL2 := `
168	Type: PoolL2
169	PoolTransferToEthAddr(1) A-B: 200 (126)
170	PoolTransferToEthAddr(0) B-C: 100 (126)`
171	l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
172	require.NoError(t, err)
173	// add AccountCreationAuths that will be used at the next batch
174	_ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "B")
175	_ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "C")
176	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
177	l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
178	// TxSelector select the transactions for the next Batch
179	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
180	require.NoError(t, err)
181	// BatchBuilder build Batch
182	zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
183	require.NoError(t, err)
184	assert.Equal(t, "7614010373759339299470010949167613050707822522530721724565424494781010548240", bb.LocalStateDB().MT.Root().BigInt().String())
185	sendProofAndCheckResp(t, zki)
186	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.LocalAccountsDB().CurrentBatch())
187	require.NoError(t, err)
188	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
189	require.NoError(t, err)
190
191	log.Debug("block:0 batch:8")
192	// simulate the PoolL2Txs of the batch8
193	batchPoolL2 = `
194	Type: PoolL2
195	PoolTransfer(0) A-B: 100 (126)
196	PoolTransfer(0) C-A: 50 (126)
197	PoolTransfer(1) B-C: 100 (126)
198	PoolExit(0) A: 100 (126)`
199	l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
200	require.NoError(t, err)
201	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
202	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
203	// TxSelector select the transactions for the next Batch
204	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
205	require.NoError(t, err)
206	// BatchBuilder build Batch
207	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
208	require.NoError(t, err)
209	assert.Equal(t, "21231789250434471575486264439945776732824482207853465397552873521865656677689", bb.LocalStateDB().MT.Root().BigInt().String())
210	sendProofAndCheckResp(t, zki)
211	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
212	require.NoError(t, err)
213	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
214	require.NoError(t, err)
215
216	log.Debug("(batch9) block:1 batch:1")
217	// simulate the PoolL2Txs of the batch9
218	batchPoolL2 = `
219	Type: PoolL2
220	PoolTransfer(0) D-A: 300 (126)
221	PoolTransfer(0) B-D: 100 (126)`
222	l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
223	require.NoError(t, err)
224	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
225	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
226	// TxSelector select the transactions for the next Batch
227	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
228	require.NoError(t, err)
229	// BatchBuilder build Batch
230	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
231	require.NoError(t, err)
232	assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String())
233	sendProofAndCheckResp(t, zki)
234	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
235	require.NoError(t, err)
236	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
237	require.NoError(t, err)
238
239	log.Debug("(batch10) block:1 batch:2")
240	l2Txs = []common.PoolL2Tx{}
241	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
242	// TxSelector select the transactions for the next Batch
243	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
244	require.NoError(t, err)
245	// BatchBuilder build Batch
246	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
247	require.NoError(t, err)
248	// same root as previous batch, as the L1CoordinatorTxs created by the
249	// Til set is not created by the TxSelector in this test
250	assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String())
251	sendProofAndCheckResp(t, zki)
252	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
253	require.NoError(t, err)
254	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
255	require.NoError(t, err)
256}
257
258// TestZKInputsExitWithFee0 checks the case where there is a PoolTxs of type
259// Exit with fee 0 for a TokenID that the Coordinator does not have it
260// registered yet
261func TestZKInputsExitWithFee0(t *testing.T) {
262	tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
263
264	var set = `
265	Type: Blockchain
266	AddToken(1)
267
268	CreateAccountDeposit(1) A: 1000
269	CreateAccountDeposit(1) B: 1000
270	CreateAccountDeposit(1) C: 1000
271	> batchL1
272	> batchL1
273
274	CreateAccountCoordinator(1) Coord
275	> batch
276	> block
277	`
278	blocks, err := tc.GenerateBlocks(set)
279	require.NoError(t, err)
280
281	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
282	txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
283
284	bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
285	require.NoError(t, err)
286	bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
287	require.NoError(t, err)
288
289	// restart nonces of TilContext, as will be set by generating directly
290	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
291	tc.RestartNonces()
292	// add tokens to HistoryDB to avoid breaking FK constrains
293	addTokens(t, tc, l2DBTxSel.DB())
294
295	selectionConfig := &txselector.SelectionConfig{
296		MaxL1UserTxs:      100,
297		TxProcessorConfig: txprocConfig,
298	}
299	configBatch := &batchbuilder.ConfigBatch{
300		TxProcessorConfig: txprocConfig,
301	}
302
303	// batch2
304	// TxSelector select the transactions for the next Batch
305	l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
306	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
307	require.NoError(t, err)
308	// BatchBuilder build Batch
309	zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
310	require.NoError(t, err)
311	assert.Equal(t, "8737171572459172806192626402462788826264011087579491137542380589998149683116", bb.LocalStateDB().MT.Root().BigInt().String())
312	h, err := zki.HashGlobalData()
313	require.NoError(t, err)
314	assert.Equal(t, "18608843755023673022528019960628191162333429206359207449879743919826610006009", h.String())
315	sendProofAndCheckResp(t, zki)
316
317	// batch3
318	batchPoolL2 := `
319	Type: PoolL2
320	PoolExit(1) A: 100 (0)`
321	l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
322	require.NoError(t, err)
323	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
324	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, nil)
325	require.NoError(t, err)
326	assert.Equal(t, 1, len(coordIdxs))
327	assert.Equal(t, 0, len(oL1UserTxs))
328	assert.Equal(t, 1, len(oL1CoordTxs))
329	assert.Equal(t, 1, len(oL2Txs))
330	assert.Equal(t, 0, len(discardedL2Txs))
331	// BatchBuilder build Batch
332	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
333	require.NoError(t, err)
334	assert.Equal(t, "18306761925365215381387147754881756804475668085493847010988306480531520370130", bb.LocalStateDB().MT.Root().BigInt().String())
335	h, err = zki.HashGlobalData()
336	require.NoError(t, err)
337	assert.Equal(t, "6651837443119278772088559395433504719862425648816904171510845286897104469889", h.String())
338	assert.Equal(t, common.EthAddrToBigInt(tc.Users["Coord"].Addr), zki.EthAddr3[0])
339	assert.Equal(t, "0", zki.EthAddr3[1].String())
340	sendProofAndCheckResp(t, zki)
341}