arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/test/til/txs_test.go
test/til/txs_test.goRaw
  1package til
  2
  3import (
  4	"math/big"
  5	"testing"
  6
  7	"github.com/hermeznetwork/hermez-node/common"
  8	"github.com/hermeznetwork/hermez-node/eth"
  9	"github.com/stretchr/testify/assert"
 10	"github.com/stretchr/testify/require"
 11)
 12
 13func TestGenerateBlocksNoBatches(t *testing.T) {
 14	set := `
 15		Type: Blockchain
 16		AddToken(1)
 17		AddToken(2)
 18
 19		CreateAccountDeposit(1) A: 11
 20		CreateAccountDeposit(2) B: 22
 21
 22		> block
 23	`
 24	tc := NewContext(eth.RollupConstMaxL1UserTx)
 25	blocks, err := tc.GenerateBlocks(set)
 26	require.Nil(t, err)
 27	assert.Equal(t, 1, len(blocks))
 28	assert.Equal(t, 0, len(blocks[0].Batches))
 29	assert.Equal(t, 2, len(blocks[0].AddedTokens))
 30	assert.Equal(t, 2, len(blocks[0].L1UserTxs))
 31}
 32
 33func TestGenerateBlocks(t *testing.T) {
 34	set := `
 35		Type: Blockchain
 36		AddToken(1)
 37		AddToken(2)
 38		AddToken(3)
 39	
 40		CreateAccountDeposit(1) A: 10
 41		CreateAccountDeposit(2) A: 20
 42		CreateAccountDeposit(1) B: 5
 43		CreateAccountDeposit(1) C: 5
 44		CreateAccountDeposit(1) D: 5
 45
 46		> batchL1 // batchNum = 1
 47		> batchL1 // batchNum = 2
 48
 49		CreateAccountDepositTransfer(1) F-A: 15, 10
 50
 51		Transfer(1) A-B: 6 (1)
 52		Transfer(1) B-D: 3 (1)
 53		Transfer(1) A-D: 1 (1)
 54
 55		// set new batch
 56		> batch // batchNum = 3
 57		CreateAccountCoordinator(1) E
 58		CreateAccountCoordinator(2) B
 59
 60		DepositTransfer(1) A-B: 15, 10
 61		Transfer(1) C-A : 3 (1)
 62		Transfer(2) A-B: 15 (1)
 63		Transfer(1) A-E: 1 (1)
 64
 65		CreateAccountDeposit(1) User0: 20
 66		CreateAccountDeposit(3) User1: 20
 67		CreateAccountCoordinator(1) User1
 68		CreateAccountCoordinator(3) User0
 69		> batchL1 // batchNum = 4
 70		Transfer(1) User0-User1: 15 (1)
 71		Transfer(3) User1-User0: 15 (1)
 72		Transfer(1) A-C: 1 (1)
 73
 74		> batchL1 // batchNum = 5
 75
 76		Transfer(1) User1-User0: 1 (1)
 77
 78		> block
 79
 80		// Exits
 81		Transfer(1) A-B: 1 (1)
 82		Exit(1) A: 5 (1)
 83		
 84		> batch // batchNum = 6
 85		> block
 86
 87		// this transaction should not be generated, as it's after last
 88		// batch and last block
 89		Transfer(1) User1-User0: 1 (1)
 90	`
 91	tc := NewContext(eth.RollupConstMaxL1UserTx)
 92	blocks, err := tc.GenerateBlocks(set)
 93	require.Nil(t, err)
 94	assert.Equal(t, 2, len(blocks))
 95	assert.Equal(t, 5, len(blocks[0].Batches))
 96	assert.Equal(t, 1, len(blocks[1].Batches))
 97	assert.Equal(t, 9, len(blocks[0].L1UserTxs))
 98	assert.Equal(t, 4, len(blocks[0].Batches[3].L1CoordinatorTxs))
 99	assert.Equal(t, 0, len(blocks[1].L1UserTxs))
100
101	// Check expected values generated by each line
102	// #0: Deposit(1) A: 10
103	tc.checkL1TxParams(t, blocks[0].L1UserTxs[0], common.TxTypeCreateAccountDeposit, 1, "A", "", big.NewInt(10), nil)
104	// #1: Deposit(2) A: 20
105	tc.checkL1TxParams(t, blocks[0].L1UserTxs[1], common.TxTypeCreateAccountDeposit, 2, "A", "", big.NewInt(20), nil)
106	// // #2: Deposit(1) A: 20
107	tc.checkL1TxParams(t, blocks[0].L1UserTxs[2], common.TxTypeCreateAccountDeposit, 1, "B", "", big.NewInt(5), nil)
108	// // #3: CreateAccountDeposit(1) C: 5
109	tc.checkL1TxParams(t, blocks[0].L1UserTxs[3], common.TxTypeCreateAccountDeposit, 1, "C", "", big.NewInt(5), nil)
110	// // #4: CreateAccountDeposit(1) D: 5
111	tc.checkL1TxParams(t, blocks[0].L1UserTxs[4], common.TxTypeCreateAccountDeposit, 1, "D", "", big.NewInt(5), nil)
112	// #5: Transfer(1) A-B: 6 (1)
113	tc.checkL2TxParams(t, blocks[0].Batches[2].L2Txs[0], common.TxTypeTransfer, 1, "A", "B", big.NewInt(6), common.BatchNum(3))
114	// #6: Transfer(1) B-D: 3 (1)
115	tc.checkL2TxParams(t, blocks[0].Batches[2].L2Txs[1], common.TxTypeTransfer, 1, "B", "D", big.NewInt(3), common.BatchNum(3))
116	// #7: Transfer(1) A-D: 1 (1)
117	tc.checkL2TxParams(t, blocks[0].Batches[2].L2Txs[2], common.TxTypeTransfer, 1, "A", "D", big.NewInt(1), common.BatchNum(3))
118	// change of Batch
119	// #8: CreateAccountDepositTransfer(1) F-A: 15, 10 (3)
120	tc.checkL1TxParams(t, blocks[0].L1UserTxs[5], common.TxTypeCreateAccountDepositTransfer, 1, "F", "A", big.NewInt(15), big.NewInt(10))
121	// #9: DepositTransfer(1) A-B: 15, 10 (1)
122	tc.checkL1TxParams(t, blocks[0].L1UserTxs[6], common.TxTypeDepositTransfer, 1, "A", "B", big.NewInt(15), big.NewInt(10))
123	// #11: Transfer(1) C-A : 3 (1)
124	tc.checkL2TxParams(t, blocks[0].Batches[3].L2Txs[0], common.TxTypeTransfer, 1, "C", "A", big.NewInt(3), common.BatchNum(4))
125	// #12: Transfer(2) A-B: 15 (1)
126	tc.checkL2TxParams(t, blocks[0].Batches[3].L2Txs[1], common.TxTypeTransfer, 2, "A", "B", big.NewInt(15), common.BatchNum(4))
127	// #13: Deposit(1) User0: 20
128	tc.checkL1TxParams(t, blocks[0].L1UserTxs[7], common.TxTypeCreateAccountDeposit, 1, "User0", "", big.NewInt(20), nil)
129	// // #14: Deposit(3) User1: 20
130	tc.checkL1TxParams(t, blocks[0].L1UserTxs[8], common.TxTypeCreateAccountDeposit, 3, "User1", "", big.NewInt(20), nil)
131	// #15: Transfer(1) User0-User1: 15 (1)
132	tc.checkL2TxParams(t, blocks[0].Batches[4].L2Txs[0], common.TxTypeTransfer, 1, "User0", "User1", big.NewInt(15), common.BatchNum(5))
133	// #16: Transfer(3) User1-User0: 15 (1)
134	tc.checkL2TxParams(t, blocks[0].Batches[4].L2Txs[1], common.TxTypeTransfer, 3, "User1", "User0", big.NewInt(15), common.BatchNum(5))
135	// #17: Transfer(1) A-C: 1 (1)
136	tc.checkL2TxParams(t, blocks[0].Batches[4].L2Txs[2], common.TxTypeTransfer, 1, "A", "C", big.NewInt(1), common.BatchNum(5))
137	// change of Batch
138	// #18: Transfer(1) User1-User0: 1 (1)
139	tc.checkL2TxParams(t, blocks[1].Batches[0].L2Txs[0], common.TxTypeTransfer, 1, "User1", "User0", big.NewInt(1), common.BatchNum(6))
140	// change of Block (implies also a change of batch)
141	// #19: Transfer(1) A-B: 1 (1)
142	tc.checkL2TxParams(t, blocks[1].Batches[0].L2Txs[1], common.TxTypeTransfer, 1, "A", "B", big.NewInt(1), common.BatchNum(6))
143}
144
145func (tc *Context) checkL1TxParams(t *testing.T, tx common.L1Tx, typ common.TxType, tokenID common.TokenID, from, to string, loadAmount, amount *big.Int) {
146	assert.Equal(t, typ, tx.Type)
147	if tx.FromIdx != common.Idx(0) {
148		assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx)
149	}
150	assert.Equal(t, tc.Users[from].Addr.Hex(), tx.FromEthAddr.Hex())
151	assert.Equal(t, tc.Users[from].BJJ.Public(), tx.FromBJJ)
152	if tx.ToIdx != common.Idx(0) {
153		assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx)
154	}
155	if loadAmount != nil {
156		assert.Equal(t, loadAmount, tx.LoadAmount)
157	}
158	if amount != nil {
159		assert.Equal(t, amount, tx.Amount)
160	}
161}
162
163func (tc *Context) checkL2TxParams(t *testing.T, tx common.L2Tx, typ common.TxType, tokenID common.TokenID, from, to string, amount *big.Int, batchNum common.BatchNum) {
164	assert.Equal(t, typ, tx.Type)
165	assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx)
166	if tx.Type != common.TxTypeExit {
167		assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx)
168	}
169	if amount != nil {
170		assert.Equal(t, amount, tx.Amount)
171	}
172	assert.Equal(t, batchNum, tx.BatchNum)
173}
174
175func TestGeneratePoolL2Txs(t *testing.T) {
176	set := `
177		Type: Blockchain
178		AddToken(1)
179		AddToken(2)
180		AddToken(3)
181	
182		CreateAccountDeposit(1) A: 10
183		CreateAccountDeposit(2) A: 20
184		CreateAccountDeposit(1) B: 5
185		CreateAccountDeposit(1) C: 5
186		CreateAccountDeposit(1) User0: 5
187		CreateAccountDeposit(1) User1: 0
188		CreateAccountDeposit(3) User0: 0
189		CreateAccountDeposit(3) User1: 5
190		CreateAccountDeposit(2) B: 5
191		CreateAccountDeposit(2) D: 0
192		> batchL1
193		> batchL1
194	`
195	tc := NewContext(eth.RollupConstMaxL1UserTx)
196	_, err := tc.GenerateBlocks(set)
197	require.Nil(t, err)
198	set = `
199		Type: PoolL2
200		PoolTransfer(1) A-B: 6 (1)
201		PoolTransfer(1) B-C: 3 (1)
202		PoolTransfer(1) C-A: 3 (1)
203		PoolTransfer(1) A-B: 1 (1)
204		PoolTransfer(2) A-B: 15 (1)
205		PoolTransfer(1) User0-User1: 15 (1)
206		PoolTransfer(3) User1-User0: 15 (1)
207		PoolTransfer(2) B-D: 3 (1)
208		PoolExit(1) A: 3 (1)
209		PoolTransferToEthAddr(1) A-B: 1 (1)
210		PoolTransferToBJJ(1) A-B: 1 (1)
211	`
212	poolL2Txs, err := tc.GeneratePoolL2Txs(set)
213	require.Nil(t, err)
214	assert.Equal(t, 11, len(poolL2Txs))
215	assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
216	assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
217	assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
218	assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String())
219	assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex())
220	assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String())
221
222	assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)
223	assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
224	assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
225
226	assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[9].ToEthAddr.Hex())
227	assert.Nil(t, poolL2Txs[9].ToBJJ)
228	assert.Equal(t, common.TxTypeTransferToEthAddr, poolL2Txs[9].Type)
229	assert.Equal(t, common.FFAddr, poolL2Txs[10].ToEthAddr)
230	assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[10].ToBJJ.String())
231	assert.Equal(t, common.TxTypeTransferToBJJ, poolL2Txs[10].Type)
232
233	// load another set in the same Context
234	set = `
235		Type: PoolL2
236		PoolTransfer(1) A-B: 6 (1)
237		PoolTransfer(1) B-C: 3 (1)
238		PoolTransfer(1) A-C: 3 (1)
239	`
240	poolL2Txs, err = tc.GeneratePoolL2Txs(set)
241	require.Nil(t, err)
242	assert.Equal(t, common.Nonce(6), poolL2Txs[0].Nonce)
243	assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
244	assert.Equal(t, common.Nonce(7), poolL2Txs[2].Nonce)
245
246	// check that a PoolL2Tx can be done to a non existing ToIdx
247	set = `
248		Type: Blockchain
249		AddToken(1)
250		CreateAccountDeposit(1) A: 10
251		> batchL1
252		> batchL1
253		> block
254	`
255	tc = NewContext(eth.RollupConstMaxL1UserTx)
256	_, err = tc.GenerateBlocks(set)
257	require.Nil(t, err)
258	set = `
259		Type: PoolL2
260		PoolTransferToEthAddr(1) A-B: 3 (1)
261		PoolTransferToBJJ(1) A-C: 3 (1)
262	`
263	_, err = tc.GeneratePoolL2Txs(set)
264	require.Nil(t, err)
265	// expect error, as FromIdx=B is still not created for TokenID=1
266	set = `
267		Type: PoolL2
268		PoolTransferToEthAddr(1) B-A: 3 (1)
269		PoolTransferToBJJ(1) B-A: 3 (1)
270	`
271	_, err = tc.GeneratePoolL2Txs(set)
272	require.NotNil(t, err)
273}
274
275func TestGenerateErrors(t *testing.T) {
276	// unregistered token
277	set := `Type: Blockchain
278		CreateAccountDeposit(1) A: 5
279		> batchL1
280		`
281	tc := NewContext(eth.RollupConstMaxL1UserTx)
282	_, err := tc.GenerateBlocks(set)
283	assert.Equal(t, "Line 2: Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())
284
285	// ensure AddToken sequentiality and not using 0
286	set = `
287		Type: Blockchain
288		AddToken(0)
289	`
290	tc = NewContext(eth.RollupConstMaxL1UserTx)
291	_, err = tc.GenerateBlocks(set)
292	require.Equal(t, "Line 2: AddToken can not register TokenID 0", err.Error())
293
294	set = `
295		Type: Blockchain
296		AddToken(2)
297	`
298	tc = NewContext(eth.RollupConstMaxL1UserTx)
299	_, err = tc.GenerateBlocks(set)
300	require.Equal(t, "Line 2: AddToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())
301
302	set = `
303		Type: Blockchain
304		AddToken(1)
305		AddToken(2)
306		AddToken(3)
307		AddToken(5)
308	`
309	tc = NewContext(eth.RollupConstMaxL1UserTx)
310	_, err = tc.GenerateBlocks(set)
311	require.Equal(t, "Line 5: AddToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())
312
313	// check transactions when account is not created yet
314	set = `
315		Type: Blockchain
316		AddToken(1)
317		CreateAccountDeposit(1) A: 10
318		> batchL1
319		CreateAccountDeposit(1) B
320		Transfer(1) A-B: 6 (1)
321		> batch
322	`
323	tc = NewContext(eth.RollupConstMaxL1UserTx)
324	_, err = tc.GenerateBlocks(set)
325	require.Equal(t, "Line 5: CreateAccountDeposit(1)BTransfer(1) A-B: 6 (1)\n, err: Expected ':', found 'Transfer'", err.Error())
326	set = `
327		Type: Blockchain
328		AddToken(1)
329		CreateAccountDeposit(1) A: 10
330		> batchL1
331		CreateAccountCoordinator(1) B
332		> batchL1
333		> batch
334		Transfer(1) A-B: 6 (1)
335		> batch
336	`
337	tc = NewContext(eth.RollupConstMaxL1UserTx)
338	_, err = tc.GenerateBlocks(set)
339	require.Nil(t, err)
340
341	// check nonces
342	set = `
343		Type: Blockchain
344		AddToken(1)
345		CreateAccountDeposit(1) A: 10
346		> batchL1
347		CreateAccountCoordinator(1) B
348		> batchL1
349		Transfer(1) A-B: 6 (1)
350		Transfer(1) A-B: 6 (1) // on purpose this is moving more money that what it has in the account, Til should not fail
351		Transfer(1) B-A: 6 (1)
352		Exit(1) A: 3 (1)
353		> batch
354	`
355	tc = NewContext(eth.RollupConstMaxL1UserTx)
356	_, err = tc.GenerateBlocks(set)
357	require.Nil(t, err)
358	assert.Equal(t, common.Nonce(3), tc.Users["A"].Accounts[common.TokenID(1)].Nonce)
359	assert.Equal(t, common.Idx(256), tc.Users["A"].Accounts[common.TokenID(1)].Idx)
360	assert.Equal(t, common.Nonce(1), tc.Users["B"].Accounts[common.TokenID(1)].Nonce)
361	assert.Equal(t, common.Idx(257), tc.Users["B"].Accounts[common.TokenID(1)].Idx)
362}