hermez-node/test/transakcio/txs_test.go
test/transakcio/txs_test.goRaw
1package transakcio
2
3import (
4 "math/big"
5 "testing"
6
7 "github.com/hermeznetwork/hermez-node/common"
8 "github.com/stretchr/testify/assert"
9 "github.com/stretchr/testify/require"
10)
11
12func TestGenerateBlocks(t *testing.T) {
13 set := `
14 Type: Blockchain
15 RegisterToken(1)
16 RegisterToken(2)
17 RegisterToken(3)
18
19 CreateAccountDeposit(1) A: 10
20 CreateAccountDeposit(2) A: 20
21 CreateAccountDeposit(1) B: 5
22 CreateAccountDeposit(1) C: 5
23 CreateAccountDepositTransfer(1) D-A: 15, 10 (3)
24
25 Transfer(1) A-B: 6 (1)
26 Transfer(1) B-D: 3 (1)
27 Transfer(1) A-D: 1 (1)
28
29 // set new batch
30 > batch
31 CreateAccountDepositCoordinator(1) E
32 CreateAccountDepositCoordinator(2) B
33
34 DepositTransfer(1) A-B: 15, 10 (1)
35 Transfer(1) C-A : 3 (1)
36 Transfer(2) A-B: 15 (1)
37 Transfer(1) A-E: 1 (1)
38
39 CreateAccountDeposit(1) User0: 20
40 CreateAccountDeposit(3) User1: 20
41 CreateAccountDepositCoordinator(1) User1
42 CreateAccountDepositCoordinator(3) User0
43 Transfer(1) User0-User1: 15 (1)
44 Transfer(3) User1-User0: 15 (1)
45 Transfer(1) A-C: 1 (1)
46
47 > batch
48
49 Transfer(1) User1-User0: 1 (1)
50
51 > block
52
53 // Exits
54 Transfer(1) A-B: 1 (1)
55 Exit(1) A: 5
56 `
57 tc := NewTestContext()
58 blocks, err := tc.GenerateBlocks(set)
59 require.Nil(t, err)
60 assert.Equal(t, 2, len(blocks))
61 assert.Equal(t, 3, len(blocks[0].Batches))
62 assert.Equal(t, 1, len(blocks[1].Batches))
63 assert.Equal(t, 5, len(blocks[0].Batches[0].L1UserTxs))
64 assert.Equal(t, 4, len(blocks[0].Batches[1].L1CoordinatorTxs))
65 assert.Equal(t, 0, len(blocks[1].Batches[0].L1UserTxs))
66
67 // Check expected values generated by each line
68 // #0: Deposit(1) A: 10
69 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[0], common.TxTypeCreateAccountDeposit, 1, "A", "", big.NewInt(10), nil)
70 // #1: Deposit(2) A: 20
71 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[1], common.TxTypeCreateAccountDeposit, 2, "A", "", big.NewInt(20), nil)
72 // #2: Deposit(1) A: 20
73 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[2], common.TxTypeCreateAccountDeposit, 1, "B", "", big.NewInt(5), nil)
74 // #3: CreateAccountDeposit(1) C: 5
75 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[3], common.TxTypeCreateAccountDeposit, 1, "C", "", big.NewInt(5), nil)
76 // #4: CreateAccountDepositTransfer(1) D-A: 15, 10 (3)
77 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[4], common.TxTypeCreateAccountDepositTransfer, 1, "D", "A", big.NewInt(15), big.NewInt(10))
78 // #5: Transfer(1) A-B: 6 (1)
79 tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[0], common.TxTypeTransfer, 1, "A", "B", big.NewInt(6), common.BatchNum(0), common.Nonce(1))
80 // #6: Transfer(1) B-D: 3 (1)
81 tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[1], common.TxTypeTransfer, 1, "B", "D", big.NewInt(3), common.BatchNum(0), common.Nonce(1))
82 // #7: Transfer(1) A-D: 1 (1)
83 tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[2], common.TxTypeTransfer, 1, "A", "D", big.NewInt(1), common.BatchNum(0), common.Nonce(2))
84 // change of Batch
85 // #8: DepositTransfer(1) A-B: 15, 10 (1)
86 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[0], common.TxTypeDepositTransfer, 1, "A", "B", big.NewInt(15), big.NewInt(10))
87 // #9: Deposit(1) User0: 20
88 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[0], common.TxTypeDepositTransfer, 1, "A", "B", big.NewInt(15), big.NewInt(10))
89 // #10: Transfer(1) C-A : 3 (1)
90 tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[0], common.TxTypeTransfer, 1, "C", "A", big.NewInt(3), common.BatchNum(1), common.Nonce(1))
91 // #11: Transfer(2) A-B: 15 (1)
92 tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[1], common.TxTypeTransfer, 2, "A", "B", big.NewInt(15), common.BatchNum(1), common.Nonce(1))
93 // #12: Deposit(1) User0: 20
94 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[1], common.TxTypeCreateAccountDeposit, 1, "User0", "", big.NewInt(20), nil)
95 // #13: Deposit(3) User1: 20
96 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[2], common.TxTypeCreateAccountDeposit, 3, "User1", "", big.NewInt(20), nil)
97 // #14: Transfer(1) User0-User1: 15 (1)
98 tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[3], common.TxTypeTransfer, 1, "User0", "User1", big.NewInt(15), common.BatchNum(1), common.Nonce(1))
99 // #15: Transfer(3) User1-User0: 15 (1)
100 tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[4], common.TxTypeTransfer, 3, "User1", "User0", big.NewInt(15), common.BatchNum(1), common.Nonce(1))
101 // #16: Transfer(1) A-C: 1 (1)
102 tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[5], common.TxTypeTransfer, 1, "A", "C", big.NewInt(1), common.BatchNum(1), common.Nonce(4))
103 // change of Batch
104 // #17: Transfer(1) User1-User0: 1 (1)
105 tc.checkL2TxParams(t, blocks[0].Batches[2].L2Txs[0], common.TxTypeTransfer, 1, "User1", "User0", big.NewInt(1), common.BatchNum(2), common.Nonce(1))
106 // change of Block (implies also a change of batch)
107 // #18: Transfer(1) A-B: 1 (1)
108 tc.checkL2TxParams(t, blocks[1].Batches[0].L2Txs[0], common.TxTypeTransfer, 1, "A", "B", big.NewInt(1), common.BatchNum(3), common.Nonce(5))
109}
110
111func (tc *TestContext) checkL1TxParams(t *testing.T, tx common.L1Tx, typ common.TxType, tokenID common.TokenID, from, to string, loadAmount, amount *big.Int) {
112 assert.Equal(t, typ, tx.Type)
113 if tx.FromIdx != common.Idx(0) {
114 assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx)
115 }
116 assert.Equal(t, tc.Users[from].Addr.Hex(), tx.FromEthAddr.Hex())
117 assert.Equal(t, tc.Users[from].BJJ.Public(), tx.FromBJJ)
118 if tx.ToIdx != common.Idx(0) {
119 assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx)
120 }
121 if loadAmount != nil {
122 assert.Equal(t, loadAmount, tx.LoadAmount)
123 }
124 if amount != nil {
125 assert.Equal(t, amount, tx.Amount)
126 }
127}
128func (tc *TestContext) 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) {
129 assert.Equal(t, typ, tx.Type)
130 assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx)
131 if tx.Type != common.TxTypeExit {
132 assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx)
133 }
134 if amount != nil {
135 assert.Equal(t, amount, tx.Amount)
136 }
137 assert.Equal(t, batchNum, tx.BatchNum)
138 assert.Equal(t, nonce, tx.Nonce)
139}
140
141func TestGeneratePoolL2Txs(t *testing.T) {
142 set := `
143 Type: Blockchain
144 RegisterToken(1)
145 RegisterToken(2)
146 RegisterToken(3)
147
148 CreateAccountDeposit(1) A: 10
149 CreateAccountDeposit(2) A: 20
150 CreateAccountDeposit(1) B: 5
151 CreateAccountDeposit(1) C: 5
152 CreateAccountDeposit(1) User0: 5
153 CreateAccountDeposit(1) User1: 0
154 CreateAccountDeposit(3) User0: 0
155 CreateAccountDeposit(3) User1: 5
156 CreateAccountDeposit(2) B: 5
157 CreateAccountDeposit(2) D: 0
158 `
159 tc := NewTestContext()
160 _, err := tc.GenerateBlocks(set)
161 require.Nil(t, err)
162 set = `
163 Type: PoolL2
164 PoolTransfer(1) A-B: 6 (1)
165 PoolTransfer(1) B-C: 3 (1)
166 PoolTransfer(1) C-A: 3 (1)
167 PoolTransfer(1) A-B: 1 (1)
168 PoolTransfer(2) A-B: 15 (1)
169 PoolTransfer(1) User0-User1: 15 (1)
170 PoolTransfer(3) User1-User0: 15 (1)
171 PoolTransfer(2) B-D: 3 (1)
172 PoolExit(1) A: 3
173 `
174 poolL2Txs, err := tc.GeneratePoolL2Txs(set)
175 require.Nil(t, err)
176 assert.Equal(t, 9, len(poolL2Txs))
177 assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
178 assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
179 assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
180 assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String())
181 assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex())
182 assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String())
183
184 assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)
185 assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
186 assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
187
188 // load another set in the same TestContext
189 set = `
190 Type: PoolL2
191 PoolTransfer(1) A-B: 6 (1)
192 PoolTransfer(1) B-C: 3 (1)
193 PoolTransfer(1) A-C: 3 (1)
194 `
195 poolL2Txs, err = tc.GeneratePoolL2Txs(set)
196 require.Nil(t, err)
197 assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce)
198 assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
199 assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce)
200}
201
202func TestGenerateErrors(t *testing.T) {
203 // unregistered token
204 set := `Type: Blockchain
205 CreateAccountDeposit(1) A: 5
206 `
207 tc := NewTestContext()
208 _, err := tc.GenerateBlocks(set)
209 assert.Equal(t, "Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())
210
211 // ensure RegisterToken sequentiality and not using 0
212 set = `
213 Type: Blockchain
214 RegisterToken(0)
215 `
216 tc = NewTestContext()
217 _, err = tc.GenerateBlocks(set)
218 require.Equal(t, "RegisterToken can not register TokenID 0", err.Error())
219
220 set = `
221 Type: Blockchain
222 RegisterToken(2)
223 `
224 tc = NewTestContext()
225 _, err = tc.GenerateBlocks(set)
226 require.Equal(t, "RegisterToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())
227
228 set = `
229 Type: Blockchain
230 RegisterToken(1)
231 RegisterToken(2)
232 RegisterToken(3)
233 RegisterToken(5)
234 `
235 tc = NewTestContext()
236 _, err = tc.GenerateBlocks(set)
237 require.Equal(t, "RegisterToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())
238}