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