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.

383 lines
11 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package l2db
  2. import (
  3. "fmt"
  4. "math"
  5. "os"
  6. "testing"
  7. "time"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/hermeznetwork/hermez-node/log"
  10. "github.com/hermeznetwork/hermez-node/test"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. var l2DB *L2DB
  14. func TestMain(m *testing.M) {
  15. // init DB
  16. var err error
  17. pass := os.Getenv("POSTGRES_PASS")
  18. l2DB, err = NewL2DB(5432, "localhost", "hermez", pass, "l2", 10, 100, 24*time.Hour)
  19. if err != nil {
  20. log.Error("L2DB migration failed: " + err.Error())
  21. panic(err)
  22. } else {
  23. log.Debug("L2DB migration succed")
  24. }
  25. // Run tests
  26. result := m.Run()
  27. // Close DB
  28. if err := l2DB.Close(); err != nil {
  29. fmt.Println("Error closing the history DB:", err)
  30. }
  31. os.Exit(result)
  32. }
  33. func TestAddTx(t *testing.T) {
  34. const nInserts = 20
  35. test.CleanL2DB(l2DB.DB())
  36. txs := test.GenPoolTxs(nInserts)
  37. for _, tx := range txs {
  38. err := l2DB.AddTx(tx)
  39. assert.NoError(t, err)
  40. fetchedTx, err := l2DB.GetTx(tx.TxID)
  41. assert.NoError(t, err)
  42. assert.Equal(t, tx.Timestamp.Unix(), fetchedTx.Timestamp.Unix())
  43. tx.Timestamp = fetchedTx.Timestamp
  44. assert.Equal(t, tx.AbsoluteFeeUpdate.Unix(), fetchedTx.AbsoluteFeeUpdate.Unix())
  45. tx.Timestamp = fetchedTx.Timestamp
  46. tx.AbsoluteFeeUpdate = fetchedTx.AbsoluteFeeUpdate
  47. assert.Equal(t, tx, fetchedTx)
  48. }
  49. }
  50. func BenchmarkAddTx(b *testing.B) {
  51. const nInserts = 20
  52. test.CleanL2DB(l2DB.DB())
  53. txs := test.GenPoolTxs(nInserts)
  54. now := time.Now()
  55. for _, tx := range txs {
  56. _ = l2DB.AddTx(tx)
  57. }
  58. elapsedTime := time.Since(now)
  59. fmt.Println("Time to insert 2048 txs:", elapsedTime)
  60. }
  61. func TestGetPending(t *testing.T) {
  62. const nInserts = 20
  63. test.CleanL2DB(l2DB.DB())
  64. txs := test.GenPoolTxs(nInserts)
  65. var pendingTxs []*common.PoolL2Tx
  66. for _, tx := range txs {
  67. err := l2DB.AddTx(tx)
  68. assert.NoError(t, err)
  69. if tx.State == common.PoolL2TxStatePending {
  70. pendingTxs = append(pendingTxs, tx)
  71. }
  72. }
  73. fetchedTxs, err := l2DB.GetPendingTxs()
  74. assert.NoError(t, err)
  75. assert.Equal(t, len(pendingTxs), len(fetchedTxs))
  76. for i, fetchedTx := range fetchedTxs {
  77. assert.Equal(t, pendingTxs[i].Timestamp.Unix(), fetchedTx.Timestamp.Unix())
  78. pendingTxs[i].Timestamp = fetchedTx.Timestamp
  79. assert.Equal(t, pendingTxs[i].AbsoluteFeeUpdate.Unix(), fetchedTx.AbsoluteFeeUpdate.Unix())
  80. pendingTxs[i].AbsoluteFeeUpdate = fetchedTx.AbsoluteFeeUpdate
  81. assert.Equal(t, pendingTxs[i], fetchedTx)
  82. }
  83. }
  84. func TestStartForging(t *testing.T) {
  85. // Generate txs
  86. const nInserts = 60
  87. const fakeBatchNum common.BatchNum = 33
  88. test.CleanL2DB(l2DB.DB())
  89. txs := test.GenPoolTxs(nInserts)
  90. var startForgingTxIDs []common.TxID
  91. randomizer := 0
  92. // Add txs to DB
  93. for _, tx := range txs {
  94. err := l2DB.AddTx(tx)
  95. assert.NoError(t, err)
  96. if tx.State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  97. randomizer++
  98. startForgingTxIDs = append(startForgingTxIDs, tx.TxID)
  99. }
  100. }
  101. // Start forging txs
  102. err := l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
  103. assert.NoError(t, err)
  104. // Fetch txs and check that they've been updated correctly
  105. for _, id := range startForgingTxIDs {
  106. fetchedTx, err := l2DB.GetTx(id)
  107. assert.NoError(t, err)
  108. assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
  109. assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
  110. }
  111. }
  112. func TestDoneForging(t *testing.T) {
  113. // Generate txs
  114. const nInserts = 60
  115. const fakeBatchNum common.BatchNum = 33
  116. test.CleanL2DB(l2DB.DB())
  117. txs := test.GenPoolTxs(nInserts)
  118. var doneForgingTxIDs []common.TxID
  119. randomizer := 0
  120. // Add txs to DB
  121. for _, tx := range txs {
  122. err := l2DB.AddTx(tx)
  123. assert.NoError(t, err)
  124. if tx.State == common.PoolL2TxStateForging && randomizer%2 == 0 {
  125. randomizer++
  126. doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
  127. }
  128. }
  129. // Start forging txs
  130. err := l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
  131. assert.NoError(t, err)
  132. // Fetch txs and check that they've been updated correctly
  133. for _, id := range doneForgingTxIDs {
  134. fetchedTx, err := l2DB.GetTx(id)
  135. assert.NoError(t, err)
  136. assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
  137. assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
  138. }
  139. }
  140. func TestInvalidate(t *testing.T) {
  141. // Generate txs
  142. const nInserts = 60
  143. const fakeBatchNum common.BatchNum = 33
  144. test.CleanL2DB(l2DB.DB())
  145. txs := test.GenPoolTxs(nInserts)
  146. var invalidTxIDs []common.TxID
  147. randomizer := 0
  148. // Add txs to DB
  149. for _, tx := range txs {
  150. err := l2DB.AddTx(tx)
  151. assert.NoError(t, err)
  152. if tx.State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
  153. randomizer++
  154. invalidTxIDs = append(invalidTxIDs, tx.TxID)
  155. }
  156. }
  157. // Start forging txs
  158. err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
  159. assert.NoError(t, err)
  160. // Fetch txs and check that they've been updated correctly
  161. for _, id := range invalidTxIDs {
  162. fetchedTx, err := l2DB.GetTx(id)
  163. assert.NoError(t, err)
  164. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  165. assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
  166. }
  167. }
  168. func TestCheckNonces(t *testing.T) {
  169. // Generate txs
  170. const nInserts = 60
  171. const fakeBatchNum common.BatchNum = 33
  172. test.CleanL2DB(l2DB.DB())
  173. txs := test.GenPoolTxs(nInserts)
  174. var invalidTxIDs []common.TxID
  175. // Generate accounts
  176. const nAccoutns = 2
  177. const currentNonce = 2
  178. accs := []common.Account{}
  179. for i := 0; i < nAccoutns; i++ {
  180. accs = append(accs, common.Account{
  181. Idx: common.Idx(i),
  182. Nonce: currentNonce,
  183. })
  184. }
  185. // Add txs to DB
  186. for i := 0; i < len(txs); i++ {
  187. if txs[i].State != common.PoolL2TxStateInvalid {
  188. if i%2 == 0 { // Ensure transaction will be marked as invalid due to old nonce
  189. txs[i].Nonce = accs[i%len(accs)].Nonce
  190. txs[i].FromIdx = accs[i%len(accs)].Idx
  191. invalidTxIDs = append(invalidTxIDs, txs[i].TxID)
  192. } else { // Ensure transaction will NOT be marked as invalid due to old nonce
  193. txs[i].Nonce = currentNonce + 1
  194. }
  195. }
  196. err := l2DB.AddTx(txs[i])
  197. assert.NoError(t, err)
  198. }
  199. // Start forging txs
  200. err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
  201. assert.NoError(t, err)
  202. // Fetch txs and check that they've been updated correctly
  203. for _, id := range invalidTxIDs {
  204. fetchedTx, err := l2DB.GetTx(id)
  205. assert.NoError(t, err)
  206. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  207. assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
  208. }
  209. }
  210. func TestUpdateTxValue(t *testing.T) {
  211. // Generate txs
  212. const nInserts = 255 // Force all possible fee selector values
  213. test.CleanL2DB(l2DB.DB())
  214. txs := test.GenPoolTxs(nInserts)
  215. // Generate tokens
  216. const nTokens = 2
  217. tokens := []common.Token{}
  218. for i := 0; i < nTokens; i++ {
  219. tokens = append(tokens, common.Token{
  220. TokenID: common.TokenID(i),
  221. USD: float64(i) * 1.3,
  222. })
  223. }
  224. // Add txs to DB
  225. for i := 0; i < len(txs); i++ {
  226. // Set Token
  227. token := tokens[i%len(tokens)]
  228. txs[i].TokenID = token.TokenID
  229. // Insert to DB
  230. err := l2DB.AddTx(txs[i])
  231. assert.NoError(t, err)
  232. // Set USD values (for comparing results when fetching from DB)
  233. txs[i].USD = txs[i].AmountFloat * token.USD
  234. if txs[i].Fee == 0 {
  235. txs[i].AbsoluteFee = 0
  236. } else if txs[i].Fee <= 32 {
  237. txs[i].AbsoluteFee = txs[i].USD * math.Pow(10, -24+(float64(txs[i].Fee)/2))
  238. } else if txs[i].Fee <= 223 {
  239. txs[i].AbsoluteFee = txs[i].USD * math.Pow(10, -8+(0.041666666666667*(float64(txs[i].Fee)-32)))
  240. } else {
  241. txs[i].AbsoluteFee = txs[i].USD * math.Pow(10, float64(txs[i].Fee)-224)
  242. }
  243. }
  244. // Update token value
  245. err := l2DB.UpdateTxValue(tokens)
  246. assert.NoError(t, err)
  247. // Fetch txs and check that they've been updated correctly
  248. for _, tx := range txs {
  249. fetchedTx, err := l2DB.GetTx(tx.TxID)
  250. assert.NoError(t, err)
  251. if fetchedTx.USD > tx.USD {
  252. assert.Less(t, 0.999, tx.USD/fetchedTx.USD)
  253. } else if fetchedTx.USD < tx.USD {
  254. assert.Less(t, 0.999, fetchedTx.USD/tx.USD)
  255. }
  256. if fetchedTx.AbsoluteFee > tx.AbsoluteFee {
  257. assert.Less(t, 0.999, tx.AbsoluteFee/fetchedTx.AbsoluteFee)
  258. } else if fetchedTx.AbsoluteFee < tx.AbsoluteFee {
  259. assert.Less(t, 0.999, fetchedTx.AbsoluteFee/tx.AbsoluteFee)
  260. }
  261. // Time is set in the DB, so it cannot be compared exactly
  262. assert.Greater(t, float64(15*time.Second), time.Since(fetchedTx.AbsoluteFeeUpdate).Seconds())
  263. }
  264. }
  265. func TestReorg(t *testing.T) {
  266. // Generate txs
  267. const nInserts = 20
  268. const lastValidBatch common.BatchNum = 20
  269. const reorgBatch common.BatchNum = lastValidBatch + 1
  270. test.CleanL2DB(l2DB.DB())
  271. txs := test.GenPoolTxs(nInserts)
  272. // Add txs to the DB
  273. reorgedTxIDs := []common.TxID{}
  274. nonReorgedTxIDs := []common.TxID{}
  275. for i := 0; i < len(txs); i++ {
  276. if txs[i].State == common.PoolL2TxStateForged || txs[i].State == common.PoolL2TxStateInvalid {
  277. txs[i].BatchNum = reorgBatch
  278. reorgedTxIDs = append(reorgedTxIDs, txs[i].TxID)
  279. } else {
  280. txs[i].BatchNum = lastValidBatch
  281. nonReorgedTxIDs = append(nonReorgedTxIDs, txs[i].TxID)
  282. }
  283. err := l2DB.AddTx(txs[i])
  284. assert.NoError(t, err)
  285. }
  286. err := l2DB.Reorg(lastValidBatch)
  287. assert.NoError(t, err)
  288. var nullBatchNum common.BatchNum
  289. for _, id := range reorgedTxIDs {
  290. tx, err := l2DB.GetTx(id)
  291. assert.NoError(t, err)
  292. assert.Equal(t, nullBatchNum, tx.BatchNum)
  293. assert.Equal(t, common.PoolL2TxStatePending, tx.State)
  294. }
  295. for _, id := range nonReorgedTxIDs {
  296. tx, err := l2DB.GetTx(id)
  297. assert.NoError(t, err)
  298. assert.Equal(t, lastValidBatch, tx.BatchNum)
  299. }
  300. }
  301. func TestPurge(t *testing.T) {
  302. // Generate txs
  303. nInserts := l2DB.maxTxs + 20
  304. test.CleanL2DB(l2DB.DB())
  305. txs := test.GenPoolTxs(int(nInserts))
  306. deletedIDs := []common.TxID{}
  307. keepedIDs := []common.TxID{}
  308. const toDeleteBatchNum common.BatchNum = 30
  309. safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
  310. // Add txs to the DB
  311. for i := 0; i < int(l2DB.maxTxs); i++ {
  312. if i%1 == 0 { // keep tx
  313. txs[i].BatchNum = safeBatchNum
  314. keepedIDs = append(keepedIDs, txs[i].TxID)
  315. } else if i%2 == 0 { // delete after safety period
  316. txs[i].BatchNum = toDeleteBatchNum
  317. if i%3 == 0 {
  318. txs[i].State = common.PoolL2TxStateForged
  319. } else {
  320. txs[i].State = common.PoolL2TxStateInvalid
  321. }
  322. deletedIDs = append(deletedIDs, txs[i].TxID)
  323. }
  324. err := l2DB.AddTx(txs[i])
  325. assert.NoError(t, err)
  326. }
  327. for i := int(l2DB.maxTxs); i < len(txs); i++ {
  328. // Delete after TTL
  329. txs[i].Timestamp = time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
  330. deletedIDs = append(deletedIDs, txs[i].TxID)
  331. err := l2DB.AddTx(txs[i])
  332. assert.NoError(t, err)
  333. }
  334. // Purge txs
  335. err := l2DB.Purge(safeBatchNum - 1)
  336. assert.NoError(t, err)
  337. // Check results
  338. for _, id := range deletedIDs {
  339. tx, err := l2DB.GetTx(id)
  340. if err == nil {
  341. log.Debug(tx)
  342. }
  343. assert.Error(t, err)
  344. }
  345. for _, id := range keepedIDs {
  346. _, err := l2DB.GetTx(id)
  347. assert.NoError(t, err)
  348. }
  349. }
  350. func TestAuth(t *testing.T) {
  351. test.CleanL2DB(l2DB.DB())
  352. const nAuths = 5
  353. // Generate authorizations
  354. auths := test.GenAuths(nAuths)
  355. for i := 0; i < len(auths); i++ {
  356. // Add to the DB
  357. err := l2DB.AddAccountCreationAuth(auths[i])
  358. assert.NoError(t, err)
  359. // Fetch from DB
  360. auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
  361. assert.NoError(t, err)
  362. // Check fetched vs generated
  363. assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
  364. assert.Equal(t, auths[i].BJJ, auth.BJJ)
  365. assert.Equal(t, auths[i].Signature, auth.Signature)
  366. assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
  367. }
  368. }