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 (3)
 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		CreateAccountDepositCoordinator(1) E
 58		CreateAccountDepositCoordinator(2) B
 59
 60		DepositTransfer(1) A-B: 15, 10 (1)
 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		CreateAccountDepositCoordinator(1) User1
 68		CreateAccountDepositCoordinator(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
 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
210	`
211	poolL2Txs, err := tc.GeneratePoolL2Txs(set)
212	require.Nil(t, err)
213	assert.Equal(t, 9, len(poolL2Txs))
214	assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
215	assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
216	assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
217	assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String())
218	assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex())
219	assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String())
220
221	assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)
222	assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
223	assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
224
225	// load another set in the same Context
226	set = `
227		Type: PoolL2
228		PoolTransfer(1) A-B: 6 (1)
229		PoolTransfer(1) B-C: 3 (1)
230		PoolTransfer(1) A-C: 3 (1)
231	`
232	poolL2Txs, err = tc.GeneratePoolL2Txs(set)
233	require.Nil(t, err)
234	assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce)
235	assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
236	assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce)
237}
238
239func TestGenerateErrors(t *testing.T) {
240	// unregistered token
241	set := `Type: Blockchain
242		CreateAccountDeposit(1) A: 5
243		> batchL1
244		`
245	tc := NewContext(eth.RollupConstMaxL1UserTx)
246	_, err := tc.GenerateBlocks(set)
247	assert.Equal(t, "Line 2: Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())
248
249	// ensure AddToken sequentiality and not using 0
250	set = `
251		Type: Blockchain
252		AddToken(0)
253	`
254	tc = NewContext(eth.RollupConstMaxL1UserTx)
255	_, err = tc.GenerateBlocks(set)
256	require.Equal(t, "Line 2: AddToken can not register TokenID 0", err.Error())
257
258	set = `
259		Type: Blockchain
260		AddToken(2)
261	`
262	tc = NewContext(eth.RollupConstMaxL1UserTx)
263	_, err = tc.GenerateBlocks(set)
264	require.Equal(t, "Line 2: AddToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())
265
266	set = `
267		Type: Blockchain
268		AddToken(1)
269		AddToken(2)
270		AddToken(3)
271		AddToken(5)
272	`
273	tc = NewContext(eth.RollupConstMaxL1UserTx)
274	_, err = tc.GenerateBlocks(set)
275	require.Equal(t, "Line 5: AddToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())
276
277	// check transactions when account is not created yet
278	set = `
279		Type: Blockchain
280		AddToken(1)
281		CreateAccountDeposit(1) A: 10
282		> batchL1
283		CreateAccountDeposit(1) B
284		Transfer(1) A-B: 6 (1)
285		> batch
286	`
287	tc = NewContext(eth.RollupConstMaxL1UserTx)
288	_, err = tc.GenerateBlocks(set)
289	require.Equal(t, "Line 5: CreateAccountDeposit(1)BTransfer(1) A-B: 6 (1)\n, err: Expected ':', found 'Transfer'", err.Error())
290	set = `
291		Type: Blockchain
292		AddToken(1)
293		CreateAccountDeposit(1) A: 10
294		> batchL1
295		CreateAccountDepositCoordinator(1) B
296		> batchL1
297		> batch
298		Transfer(1) A-B: 6 (1)
299		> batch
300	`
301	tc = NewContext(eth.RollupConstMaxL1UserTx)
302	_, err = tc.GenerateBlocks(set)
303	require.Nil(t, err)
304
305	// check nonces
306	set = `
307		Type: Blockchain
308		AddToken(1)
309		CreateAccountDeposit(1) A: 10
310		> batchL1
311		CreateAccountDepositCoordinator(1) B
312		> batchL1
313		Transfer(1) A-B: 6 (1)
314		Transfer(1) A-B: 6 (1) // on purpose this is moving more money that what it has in the account, Til should not fail
315		Transfer(1) B-A: 6 (1)
316		Exit(1) A: 3
317		> batch
318	`
319	tc = NewContext(eth.RollupConstMaxL1UserTx)
320	_, err = tc.GenerateBlocks(set)
321	require.Nil(t, err)
322	assert.Equal(t, common.Nonce(3), tc.Users["A"].Accounts[common.TokenID(1)].Nonce)
323	assert.Equal(t, common.Idx(256), tc.Users["A"].Accounts[common.TokenID(1)].Idx)
324	assert.Equal(t, common.Nonce(1), tc.Users["B"].Accounts[common.TokenID(1)].Nonce)
325	assert.Equal(t, common.Idx(257), tc.Users["B"].Accounts[common.TokenID(1)].Idx)
326}