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.

238 lines
8.9 KiB

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