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.

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