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.

350 lines
9.1 KiB

  1. package statedb
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "io/ioutil"
  6. "math/big"
  7. "testing"
  8. ethCrypto "github.com/ethereum/go-ethereum/crypto"
  9. "github.com/hermeznetwork/hermez-node/common"
  10. "github.com/iden3/go-iden3-crypto/babyjub"
  11. "github.com/iden3/go-merkletree/db"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. )
  15. func newAccount(t *testing.T, i int) *common.Account {
  16. var sk babyjub.PrivateKey
  17. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  18. require.Nil(t, err)
  19. pk := sk.Public()
  20. key, err := ethCrypto.GenerateKey()
  21. require.Nil(t, err)
  22. address := ethCrypto.PubkeyToAddress(key.PublicKey)
  23. return &common.Account{
  24. TokenID: common.TokenID(i),
  25. Nonce: common.Nonce(i),
  26. Balance: big.NewInt(1000),
  27. PublicKey: pk,
  28. EthAddr: address,
  29. }
  30. }
  31. func TestNewStateDBIntermediateState(t *testing.T) {
  32. dir, err := ioutil.TempDir("", "tmpdb")
  33. require.Nil(t, err)
  34. sdb, err := NewStateDB(dir, TypeTxSelector, 0)
  35. assert.Nil(t, err)
  36. // test values
  37. k0 := []byte("testkey0")
  38. k1 := []byte("testkey1")
  39. v0 := []byte("testvalue0")
  40. v1 := []byte("testvalue1")
  41. // store some data
  42. tx, err := sdb.db.NewTx()
  43. assert.Nil(t, err)
  44. err = tx.Put(k0, v0)
  45. assert.Nil(t, err)
  46. err = tx.Commit()
  47. assert.Nil(t, err)
  48. v, err := sdb.db.Get(k0)
  49. assert.Nil(t, err)
  50. assert.Equal(t, v0, v)
  51. // call NewStateDB which should get the db at the last checkpoint state
  52. // executing a Reset (discarding the last 'testkey0'&'testvalue0' data)
  53. sdb, err = NewStateDB(dir, TypeTxSelector, 0)
  54. assert.Nil(t, err)
  55. v, err = sdb.db.Get(k0)
  56. assert.NotNil(t, err)
  57. assert.Equal(t, db.ErrNotFound, err)
  58. assert.Nil(t, v)
  59. // store the same data from the beginning that has ben lost since last NewStateDB
  60. tx, err = sdb.db.NewTx()
  61. assert.Nil(t, err)
  62. err = tx.Put(k0, v0)
  63. assert.Nil(t, err)
  64. err = tx.Commit()
  65. assert.Nil(t, err)
  66. v, err = sdb.db.Get(k0)
  67. assert.Nil(t, err)
  68. assert.Equal(t, v0, v)
  69. // make checkpoints with the current state
  70. bn, err := sdb.GetCurrentBatch()
  71. assert.Nil(t, err)
  72. assert.Equal(t, common.BatchNum(0), bn)
  73. err = sdb.MakeCheckpoint()
  74. assert.Nil(t, err)
  75. bn, err = sdb.GetCurrentBatch()
  76. assert.Nil(t, err)
  77. assert.Equal(t, common.BatchNum(1), bn)
  78. // write more data
  79. tx, err = sdb.db.NewTx()
  80. assert.Nil(t, err)
  81. err = tx.Put(k1, v1)
  82. assert.Nil(t, err)
  83. err = tx.Commit()
  84. assert.Nil(t, err)
  85. v, err = sdb.db.Get(k1)
  86. assert.Nil(t, err)
  87. assert.Equal(t, v1, v)
  88. // call NewStateDB which should get the db at the last checkpoint state
  89. // executing a Reset (discarding the last 'testkey1'&'testvalue1' data)
  90. sdb, err = NewStateDB(dir, TypeTxSelector, 0)
  91. assert.Nil(t, err)
  92. v, err = sdb.db.Get(k0)
  93. assert.Nil(t, err)
  94. assert.Equal(t, v0, v)
  95. v, err = sdb.db.Get(k1)
  96. assert.NotNil(t, err)
  97. assert.Equal(t, db.ErrNotFound, err)
  98. assert.Nil(t, v)
  99. }
  100. func TestStateDBWithoutMT(t *testing.T) {
  101. dir, err := ioutil.TempDir("", "tmpdb")
  102. require.Nil(t, err)
  103. sdb, err := NewStateDB(dir, TypeTxSelector, 0)
  104. assert.Nil(t, err)
  105. // create test accounts
  106. var accounts []*common.Account
  107. for i := 0; i < 100; i++ {
  108. accounts = append(accounts, newAccount(t, i))
  109. }
  110. // get non-existing account, expecting an error
  111. unexistingAccount := common.Idx(1)
  112. _, err = sdb.GetAccount(&unexistingAccount)
  113. assert.NotNil(t, err)
  114. assert.Equal(t, db.ErrNotFound, err)
  115. // add test accounts
  116. for i := 0; i < len(accounts); i++ {
  117. _, err = sdb.CreateAccount(common.Idx(i), accounts[i])
  118. assert.Nil(t, err)
  119. }
  120. for i := 0; i < len(accounts); i++ {
  121. existingAccount := common.Idx(i)
  122. accGetted, err := sdb.GetAccount(&existingAccount)
  123. assert.Nil(t, err)
  124. assert.Equal(t, accounts[i], accGetted)
  125. }
  126. // try already existing idx and get error
  127. existingAccount := common.Idx(1)
  128. _, err = sdb.GetAccount(&existingAccount) // check that exist
  129. assert.Nil(t, err)
  130. _, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
  131. assert.NotNil(t, err)
  132. assert.Equal(t, ErrAccountAlreadyExists, err)
  133. // update accounts
  134. for i := 0; i < len(accounts); i++ {
  135. accounts[i].Nonce = accounts[i].Nonce + 1
  136. existingAccount = common.Idx(i)
  137. _, err = sdb.UpdateAccount(&existingAccount, accounts[i])
  138. assert.Nil(t, err)
  139. }
  140. _, err = sdb.MTGetProof(common.Idx(1))
  141. assert.NotNil(t, err)
  142. assert.Equal(t, ErrStateDBWithoutMT, err)
  143. }
  144. func TestStateDBWithMT(t *testing.T) {
  145. dir, err := ioutil.TempDir("", "tmpdb")
  146. require.Nil(t, err)
  147. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  148. assert.Nil(t, err)
  149. // create test accounts
  150. var accounts []*common.Account
  151. for i := 0; i < 20; i++ {
  152. accounts = append(accounts, newAccount(t, i))
  153. }
  154. // get non-existing account, expecting an error
  155. accountIdx := common.Idx(1)
  156. _, err = sdb.GetAccount(&accountIdx)
  157. assert.NotNil(t, err)
  158. assert.Equal(t, db.ErrNotFound, err)
  159. // add test accounts
  160. for i := 0; i < len(accounts); i++ {
  161. _, err = sdb.CreateAccount(common.Idx(i), accounts[i])
  162. assert.Nil(t, err)
  163. }
  164. for i := 0; i < len(accounts); i++ {
  165. accountIdx = common.Idx(i)
  166. accGetted, err := sdb.GetAccount(&accountIdx)
  167. assert.Nil(t, err)
  168. assert.Equal(t, accounts[i], accGetted)
  169. }
  170. // try already existing idx and get error
  171. accountIdx = 1
  172. _, err = sdb.GetAccount(&accountIdx) // check that exist
  173. assert.Nil(t, err)
  174. _, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
  175. assert.NotNil(t, err)
  176. assert.Equal(t, ErrAccountAlreadyExists, err)
  177. _, err = sdb.MTGetProof(common.Idx(1))
  178. assert.Nil(t, err)
  179. // update accounts
  180. for i := 0; i < len(accounts); i++ {
  181. accounts[i].Nonce = accounts[i].Nonce + 1
  182. accountIdx = common.Idx(i)
  183. _, err = sdb.UpdateAccount(&accountIdx, accounts[i])
  184. assert.Nil(t, err)
  185. }
  186. accountIdx = 1
  187. a, err := sdb.GetAccount(&accountIdx) // check that account value has been updated
  188. assert.Nil(t, err)
  189. assert.Equal(t, accounts[1].Nonce, a.Nonce)
  190. }
  191. func TestCheckpoints(t *testing.T) {
  192. dir, err := ioutil.TempDir("", "sdb")
  193. require.Nil(t, err)
  194. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  195. assert.Nil(t, err)
  196. // create test accounts
  197. var accounts []*common.Account
  198. for i := 0; i < 10; i++ {
  199. accounts = append(accounts, newAccount(t, i))
  200. }
  201. // add test accounts
  202. for i := 0; i < len(accounts); i++ {
  203. _, err = sdb.CreateAccount(common.Idx(i), accounts[i])
  204. assert.Nil(t, err)
  205. }
  206. // do checkpoints and check that currentBatch is correct
  207. err = sdb.MakeCheckpoint()
  208. assert.Nil(t, err)
  209. cb, err := sdb.GetCurrentBatch()
  210. assert.Nil(t, err)
  211. assert.Equal(t, common.BatchNum(1), cb)
  212. for i := 1; i < 10; i++ {
  213. err = sdb.MakeCheckpoint()
  214. assert.Nil(t, err)
  215. cb, err = sdb.GetCurrentBatch()
  216. assert.Nil(t, err)
  217. assert.Equal(t, common.BatchNum(i+1), cb)
  218. }
  219. // printCheckpoints(t, sdb.path)
  220. // reset checkpoint
  221. err = sdb.Reset(3)
  222. assert.Nil(t, err)
  223. // check that reset can be repeated (as there exist the 'current' and
  224. // 'BatchNum3', from where the 'current' is a copy)
  225. err = sdb.Reset(3)
  226. require.Nil(t, err)
  227. // check that currentBatch is as expected after Reset
  228. cb, err = sdb.GetCurrentBatch()
  229. assert.Nil(t, err)
  230. assert.Equal(t, common.BatchNum(3), cb)
  231. // advance one checkpoint and check that currentBatch is fine
  232. err = sdb.MakeCheckpoint()
  233. assert.Nil(t, err)
  234. cb, err = sdb.GetCurrentBatch()
  235. assert.Nil(t, err)
  236. assert.Equal(t, common.BatchNum(4), cb)
  237. err = sdb.DeleteCheckpoint(common.BatchNum(9))
  238. assert.Nil(t, err)
  239. err = sdb.DeleteCheckpoint(common.BatchNum(10))
  240. assert.Nil(t, err)
  241. err = sdb.DeleteCheckpoint(common.BatchNum(9)) // does not exist, should return err
  242. assert.NotNil(t, err)
  243. err = sdb.DeleteCheckpoint(common.BatchNum(11)) // does not exist, should return err
  244. assert.NotNil(t, err)
  245. // Create a LocalStateDB from the initial StateDB
  246. dirLocal, err := ioutil.TempDir("", "ldb")
  247. require.Nil(t, err)
  248. ldb, err := NewLocalStateDB(dirLocal, sdb, TypeBatchBuilder, 32)
  249. assert.Nil(t, err)
  250. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  251. err = ldb.Reset(4, true)
  252. assert.Nil(t, err)
  253. // check that currentBatch is 4 after the Reset
  254. cb, err = ldb.GetCurrentBatch()
  255. assert.Nil(t, err)
  256. assert.Equal(t, common.BatchNum(4), cb)
  257. // advance one checkpoint in ldb
  258. err = ldb.MakeCheckpoint()
  259. assert.Nil(t, err)
  260. cb, err = ldb.GetCurrentBatch()
  261. assert.Nil(t, err)
  262. assert.Equal(t, common.BatchNum(5), cb)
  263. // Create a 2nd LocalStateDB from the initial StateDB
  264. dirLocal2, err := ioutil.TempDir("", "ldb2")
  265. require.Nil(t, err)
  266. ldb2, err := NewLocalStateDB(dirLocal2, sdb, TypeBatchBuilder, 32)
  267. assert.Nil(t, err)
  268. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  269. err = ldb2.Reset(4, true)
  270. assert.Nil(t, err)
  271. // check that currentBatch is 4 after the Reset
  272. cb, err = ldb2.GetCurrentBatch()
  273. assert.Nil(t, err)
  274. assert.Equal(t, common.BatchNum(4), cb)
  275. // advance one checkpoint in ldb2
  276. err = ldb2.MakeCheckpoint()
  277. assert.Nil(t, err)
  278. cb, err = ldb2.GetCurrentBatch()
  279. assert.Nil(t, err)
  280. assert.Equal(t, common.BatchNum(5), cb)
  281. debug := false
  282. if debug {
  283. printCheckpoints(t, sdb.path)
  284. printCheckpoints(t, ldb.path)
  285. printCheckpoints(t, ldb2.path)
  286. }
  287. }
  288. func printCheckpoints(t *testing.T, path string) {
  289. files, err := ioutil.ReadDir(path)
  290. assert.Nil(t, err)
  291. fmt.Println(path)
  292. for _, f := range files {
  293. fmt.Println(" " + f.Name())
  294. }
  295. }