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), common.Nonce(1))
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), common.Nonce(1))
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), common.Nonce(2))
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), common.Nonce(1))
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), common.Nonce(1))
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), common.Nonce(1))
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), common.Nonce(1))
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), common.Nonce(4))
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), common.Nonce(1))
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), common.Nonce(5))
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, nonce common.Nonce) {
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	assert.Equal(t, nonce, tx.Nonce)
174}
175
176func TestGeneratePoolL2Txs(t *testing.T) {
177	set := `
178		Type: Blockchain
179		AddToken(1)
180		AddToken(2)
181		AddToken(3)
182	
183		CreateAccountDeposit(1) A: 10
184		CreateAccountDeposit(2) A: 20
185		CreateAccountDeposit(1) B: 5
186		CreateAccountDeposit(1) C: 5
187		CreateAccountDeposit(1) User0: 5
188		CreateAccountDeposit(1) User1: 0
189		CreateAccountDeposit(3) User0: 0
190		CreateAccountDeposit(3) User1: 5
191		CreateAccountDeposit(2) B: 5
192		CreateAccountDeposit(2) D: 0
193		> batchL1
194		> batchL1
195	`
196	tc := NewContext(eth.RollupConstMaxL1UserTx)
197	_, err := tc.GenerateBlocks(set)
198	require.Nil(t, err)
199	set = `
200		Type: PoolL2
201		PoolTransfer(1) A-B: 6 (1)
202		PoolTransfer(1) B-C: 3 (1)
203		PoolTransfer(1) C-A: 3 (1)
204		PoolTransfer(1) A-B: 1 (1)
205		PoolTransfer(2) A-B: 15 (1)
206		PoolTransfer(1) User0-User1: 15 (1)
207		PoolTransfer(3) User1-User0: 15 (1)
208		PoolTransfer(2) B-D: 3 (1)
209		PoolExit(1) A: 3 (1)
210		PoolTransferToEthAddr(1) A-B: 1 (1)
211		PoolTransferToBJJ(1) A-B: 1 (1)
212	`
213	poolL2Txs, err := tc.GeneratePoolL2Txs(set)
214	require.Nil(t, err)
215	assert.Equal(t, 11, len(poolL2Txs))
216	assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
217	assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
218	assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
219	assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String())
220	assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex())
221	assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String())
222
223	assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)
224	assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
225	assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
226
227	assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[9].ToEthAddr.Hex())
228	assert.Nil(t, poolL2Txs[9].ToBJJ)
229	assert.Equal(t, common.TxTypeTransferToEthAddr, poolL2Txs[9].Type)
230	assert.Equal(t, common.FFAddr, poolL2Txs[10].ToEthAddr)
231	assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[10].ToBJJ.String())
232	assert.Equal(t, common.TxTypeTransferToBJJ, poolL2Txs[10].Type)
233
234	// load another set in the same Context
235	set = `
236		Type: PoolL2
237		PoolTransfer(1) A-B: 6 (1)
238		PoolTransfer(1) B-C: 3 (1)
239		PoolTransfer(1) A-C: 3 (1)
240	`
241	poolL2Txs, err = tc.GeneratePoolL2Txs(set)
242	require.Nil(t, err)
243	assert.Equal(t, common.Nonce(6), poolL2Txs[0].Nonce)
244	assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
245	assert.Equal(t, common.Nonce(7), poolL2Txs[2].Nonce)
246
247	// check that a PoolL2Tx can be done to a non existing ToIdx
248	set = `
249		Type: Blockchain
250		AddToken(1)
251		CreateAccountDeposit(1) A: 10
252		> batchL1
253		> batchL1
254		> block
255	`
256	tc = NewContext(eth.RollupConstMaxL1UserTx)
257	_, err = tc.GenerateBlocks(set)
258	require.Nil(t, err)
259	set = `
260		Type: PoolL2
261		PoolTransferToEthAddr(1) A-B: 3 (1)
262		PoolTransferToBJJ(1) A-C: 3 (1)
263	`
264	_, err = tc.GeneratePoolL2Txs(set)
265	require.Nil(t, err)
266	// expect error, as FromIdx=B is still not created for TokenID=1
267	set = `
268		Type: PoolL2
269		PoolTransferToEthAddr(1) B-A: 3 (1)
270		PoolTransferToBJJ(1) B-A: 3 (1)
271	`
272	_, err = tc.GeneratePoolL2Txs(set)
273	require.NotNil(t, err)
274}
275
276func TestGenerateErrors(t *testing.T) {
277	// unregistered token
278	set := `Type: Blockchain
279		CreateAccountDeposit(1) A: 5
280		> batchL1
281		`
282	tc := NewContext(eth.RollupConstMaxL1UserTx)
283	_, err := tc.GenerateBlocks(set)
284	assert.Equal(t, "Line 2: Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())
285
286	// ensure AddToken sequentiality and not using 0
287	set = `
288		Type: Blockchain
289		AddToken(0)
290	`
291	tc = NewContext(eth.RollupConstMaxL1UserTx)
292	_, err = tc.GenerateBlocks(set)
293	require.Equal(t, "Line 2: AddToken can not register TokenID 0", err.Error())
294
295	set = `
296		Type: Blockchain
297		AddToken(2)
298	`
299	tc = NewContext(eth.RollupConstMaxL1UserTx)
300	_, err = tc.GenerateBlocks(set)
301	require.Equal(t, "Line 2: AddToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())
302
303	set = `
304		Type: Blockchain
305		AddToken(1)
306		AddToken(2)
307		AddToken(3)
308		AddToken(5)
309	`
310	tc = NewContext(eth.RollupConstMaxL1UserTx)
311	_, err = tc.GenerateBlocks(set)
312	require.Equal(t, "Line 5: AddToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())
313
314	// check transactions when account is not created yet
315	set = `
316		Type: Blockchain
317		AddToken(1)
318		CreateAccountDeposit(1) A: 10
319		> batchL1
320		CreateAccountDeposit(1) B
321		Transfer(1) A-B: 6 (1)
322		> batch
323	`
324	tc = NewContext(eth.RollupConstMaxL1UserTx)
325	_, err = tc.GenerateBlocks(set)
326	require.Equal(t, "Line 5: CreateAccountDeposit(1)BTransfer(1) A-B: 6 (1)\n, err: Expected ':', found 'Transfer'", err.Error())
327	set = `
328		Type: Blockchain
329		AddToken(1)
330		CreateAccountDeposit(1) A: 10
331		> batchL1
332		CreateAccountCoordinator(1) B
333		> batchL1
334		> batch
335		Transfer(1) A-B: 6 (1)
336		> batch
337	`
338	tc = NewContext(eth.RollupConstMaxL1UserTx)
339	_, err = tc.GenerateBlocks(set)
340	require.Nil(t, err)
341
342	// check nonces
343	set = `
344		Type: Blockchain
345		AddToken(1)
346		CreateAccountDeposit(1) A: 10
347		> batchL1
348		CreateAccountCoordinator(1) B
349		> batchL1
350		Transfer(1) A-B: 6 (1)
351		Transfer(1) A-B: 6 (1) // on purpose this is moving more money that what it has in the account, Til should not fail
352		Transfer(1) B-A: 6 (1)
353		Exit(1) A: 3 (1)
354		> batch
355	`
356	tc = NewContext(eth.RollupConstMaxL1UserTx)
357	_, err = tc.GenerateBlocks(set)
358	require.Nil(t, err)
359	assert.Equal(t, common.Nonce(3), tc.Users["A"].Accounts[common.TokenID(1)].Nonce)
360	assert.Equal(t, common.Idx(256), tc.Users["A"].Accounts[common.TokenID(1)].Idx)
361	assert.Equal(t, common.Nonce(1), tc.Users["B"].Accounts[common.TokenID(1)].Nonce)
362	assert.Equal(t, common.Idx(257), tc.Users["B"].Accounts[common.TokenID(1)].Idx)
363}