You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
10 KiB

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