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,
 59	hermezContractAddr ethCommon.Address, username string) []byte {
 60	user := tc.Users[username]
 61	auth := &common.AccountCreationAuth{
 62		EthAddr: user.Addr,
 63		BJJ:     user.BJJ.Public().Compress(),
 64	}
 65	err := auth.Sign(func(hash []byte) ([]byte, error) {
 66		return ethCrypto.Sign(hash, user.EthSk)
 67	}, chainID, hermezContractAddr)
 68	assert.NoError(t, err)
 69
 70	err = l2DB.AddAccountCreationAuth(auth)
 71	assert.NoError(t, err)
 72	return auth.Signature
 73}
 74
 75func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address,
 76	coordUser *til.User) (*txselector.TxSelector, *l2db.L2DB, *statedb.StateDB) {
 77	pass := os.Getenv("POSTGRES_PASS")
 78	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 79	require.NoError(t, err)
 80	l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
 81
 82	dir, err := ioutil.TempDir("", "tmpSyncDB")
 83	require.NoError(t, err)
 84	defer assert.NoError(t, os.RemoveAll(dir))
 85	syncStateDB, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 86		Type: statedb.TypeSynchronizer, NLevels: 0})
 87	require.NoError(t, err)
 88
 89	txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
 90	require.NoError(t, err)
 91	defer assert.NoError(t, os.RemoveAll(dir))
 92
 93	// use Til Coord keys for tests compatibility
 94	coordAccount := &txselector.CoordAccount{
 95		Addr:                coordUser.Addr,
 96		BJJ:                 coordUser.BJJ.Public().Compress(),
 97		AccountCreationAuth: nil,
 98	}
 99	auth := common.AccountCreationAuth{
100		EthAddr: coordUser.Addr,
101		BJJ:     coordUser.BJJ.Public().Compress(),
102	}
103	err = auth.Sign(func(hash []byte) ([]byte, error) {
104		return ethCrypto.Sign(hash, coordUser.EthSk)
105	}, chainID, hermezContractAddr)
106	assert.NoError(t, err)
107	coordAccount.AccountCreationAuth = auth.Signature
108
109	txsel, err := txselector.NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
110	require.NoError(t, err)
111
112	test.WipeDB(l2DB.DB())
113
114	return txsel, l2DB, syncStateDB
115}
116
117func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) {
118	tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
119	// generate test transactions, the L1CoordinatorTxs generated by Til
120	// will be ignored at this test, as will be the TxSelector who
121	// generates them when needed
122	blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
123	require.NoError(t, err)
124
125	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
126	txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
127
128	bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
129	require.NoError(t, err)
130	bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
131	require.NoError(t, err)
132
133	// restart nonces of TilContext, as will be set by generating directly
134	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
135	tc.RestartNonces()
136
137	// add tokens to HistoryDB to avoid breaking FK constrains
138	addTokens(t, tc, l2DBTxSel.DB())
139
140	configBatch := &batchbuilder.ConfigBatch{
141		// ForgerAddress:
142		TxProcessorConfig: txprocConfig,
143	}
144
145	// loop over the first 6 batches
146	expectedRoots := []string{"0", "0",
147		"10303926118213025243660668481827257778714122989909761705455084995854999537039",
148		"8530501758307821623834726627056947648600328521261384179220598288701741436285",
149		"8530501758307821623834726627056947648600328521261384179220598288701741436285",
150		"9061858435528794221929846392270405504056106238451760714188625065949729889651"}
151	for i := 0; i < 6; i++ {
152		log.Debugf("block:0 batch:%d", i+1)
153		var l1UserTxs []common.L1Tx
154		if blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum != nil {
155			l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum])
156		}
157		// TxSelector select the transactions for the next Batch
158		coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err :=
159			txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
160		require.NoError(t, err)
161		// BatchBuilder build Batch
162		zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
163		require.NoError(t, err)
164		assert.Equal(t, expectedRoots[i], bb.LocalStateDB().MT.Root().BigInt().String())
165		sendProofAndCheckResp(t, zki)
166	}
167
168	log.Debug("block:0 batch:7")
169	// simulate the PoolL2Txs of the batch6
170	batchPoolL2 := `
171	Type: PoolL2
172	PoolTransferToEthAddr(1) A-B: 200 (126)
173	PoolTransferToEthAddr(0) B-C: 100 (126)`
174	l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
175	require.NoError(t, err)
176	// add AccountCreationAuths that will be used at the next batch
177	_ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "B")
178	_ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "C")
179	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
180	l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
181	// TxSelector select the transactions for the next Batch
182	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
183		txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
184	require.NoError(t, err)
185	// BatchBuilder build Batch
186	zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
187	require.NoError(t, err)
188	assert.Equal(t,
189		"4392049343656836675348565048374261353937130287163762821533580216441778455298",
190		bb.LocalStateDB().MT.Root().BigInt().String())
191	sendProofAndCheckResp(t, zki)
192	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
193		txsel.LocalAccountsDB().CurrentBatch())
194	require.NoError(t, err)
195	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
196	require.NoError(t, err)
197
198	log.Debug("block:0 batch:8")
199	// simulate the PoolL2Txs of the batch8
200	batchPoolL2 = `
201	Type: PoolL2
202	PoolTransfer(0) A-B: 100 (126)
203	PoolTransfer(0) C-A: 50 (126)
204	PoolTransfer(1) B-C: 100 (126)
205	PoolExit(0) A: 100 (126)`
206	l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
207	require.NoError(t, err)
208	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
209	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
210	// TxSelector select the transactions for the next Batch
211	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
212		txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
213	require.NoError(t, err)
214	// BatchBuilder build Batch
215	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
216	require.NoError(t, err)
217	assert.Equal(t,
218		"8905191229562583213069132470917469035834300549892959854483573322676101624713",
219		bb.LocalStateDB().MT.Root().BigInt().String())
220	sendProofAndCheckResp(t, zki)
221	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
222		txsel.LocalAccountsDB().CurrentBatch())
223	require.NoError(t, err)
224	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
225	require.NoError(t, err)
226
227	log.Debug("(batch9) block:1 batch:1")
228	// simulate the PoolL2Txs of the batch9
229	batchPoolL2 = `
230	Type: PoolL2
231	PoolTransfer(0) D-A: 300 (126)
232	PoolTransfer(0) B-D: 100 (126)`
233	l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
234	require.NoError(t, err)
235	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
236	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
237	// TxSelector select the transactions for the next Batch
238	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
239		txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
240	require.NoError(t, err)
241	// BatchBuilder build Batch
242	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
243	require.NoError(t, err)
244	assert.Equal(t,
245		"20593679664586247774284790801579542411781976279024409415159440382607791042723",
246		bb.LocalStateDB().MT.Root().BigInt().String())
247	sendProofAndCheckResp(t, zki)
248	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
249		txsel.LocalAccountsDB().CurrentBatch())
250	require.NoError(t, err)
251	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
252	require.NoError(t, err)
253
254	log.Debug("(batch10) block:1 batch:2")
255	l2Txs = []common.PoolL2Tx{}
256	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
257	// TxSelector select the transactions for the next Batch
258	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
259		txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
260	require.NoError(t, err)
261	// BatchBuilder build Batch
262	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
263	require.NoError(t, err)
264	// same root as previous batch, as the L1CoordinatorTxs created by the
265	// Til set is not created by the TxSelector in this test
266	assert.Equal(t,
267		"20593679664586247774284790801579542411781976279024409415159440382607791042723",
268		bb.LocalStateDB().MT.Root().BigInt().String())
269	sendProofAndCheckResp(t, zki)
270	err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
271		txsel.LocalAccountsDB().CurrentBatch())
272	require.NoError(t, err)
273	err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
274	require.NoError(t, err)
275}
276
277// TestZKInputsExitWithFee0 checks the case where there is a PoolTxs of type
278// Exit with fee 0 for a TokenID that the Coordinator does not have it
279// registered yet
280func TestZKInputsExitWithFee0(t *testing.T) {
281	tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
282
283	var set = `
284	Type: Blockchain
285	AddToken(1)
286
287	CreateAccountDeposit(1) A: 1000
288	CreateAccountDeposit(1) B: 1000
289	CreateAccountDeposit(1) C: 1000
290	> batchL1
291	> batchL1
292
293	CreateAccountCoordinator(1) Coord
294	> batch
295	> block
296	`
297	blocks, err := tc.GenerateBlocks(set)
298	require.NoError(t, err)
299
300	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
301	txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
302
303	bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
304	require.NoError(t, err)
305	bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
306	require.NoError(t, err)
307
308	// restart nonces of TilContext, as will be set by generating directly
309	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
310	tc.RestartNonces()
311	// add tokens to HistoryDB to avoid breaking FK constrains
312	addTokens(t, tc, l2DBTxSel.DB())
313
314	configBatch := &batchbuilder.ConfigBatch{
315		TxProcessorConfig: txprocConfig,
316	}
317
318	// batch2
319	// TxSelector select the transactions for the next Batch
320	l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
321	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err :=
322		txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
323	require.NoError(t, err)
324	// BatchBuilder build Batch
325	zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
326	require.NoError(t, err)
327	assert.Equal(t,
328		"3050252508378236752695438107925920517579600844238792454632938959089837319058",
329		bb.LocalStateDB().MT.Root().BigInt().String())
330	h, err := zki.HashGlobalData()
331	require.NoError(t, err)
332	assert.Equal(t,
333		"136173330006576039857485697813777018179965431269591881328654192642028135989",
334		h.String())
335	sendProofAndCheckResp(t, zki)
336
337	// batch3
338	batchPoolL2 := `
339	Type: PoolL2
340	PoolExit(1) A: 100 (0)`
341	l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
342	require.NoError(t, err)
343	addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
344	coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
345		txsel.GetL1L2TxSelection(txprocConfig, nil)
346	require.NoError(t, err)
347	assert.Equal(t, 1, len(coordIdxs))
348	assert.Equal(t, 0, len(oL1UserTxs))
349	assert.Equal(t, 1, len(oL1CoordTxs))
350	assert.Equal(t, 1, len(oL2Txs))
351	assert.Equal(t, 0, len(discardedL2Txs))
352	// BatchBuilder build Batch
353	zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
354	require.NoError(t, err)
355	assert.Equal(t,
356		"2941150582529643425331223235752941075548157545257982041291886277157404095484",
357		bb.LocalStateDB().MT.Root().BigInt().String())
358	h, err = zki.HashGlobalData()
359	require.NoError(t, err)
360	assert.Equal(t,
361		"11526955144859107275861838429358092025337347677758832533226842081116224550335",
362		h.String())
363	assert.Equal(t, common.EthAddrToBigInt(tc.Users["Coord"].Addr), zki.EthAddr3[0])
364	assert.Equal(t, "0", zki.EthAddr3[1].String())
365	sendProofAndCheckResp(t, zki)
366}