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.

345 lines
9.0 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. _, err = sdb.GetAccount(common.Idx(1))
  156. assert.NotNil(t, err)
  157. assert.Equal(t, db.ErrNotFound, err)
  158. // add test accounts
  159. for i := 0; i < len(accounts); i++ {
  160. _, err = sdb.CreateAccount(common.Idx(i), accounts[i])
  161. assert.Nil(t, err)
  162. }
  163. for i := 0; i < len(accounts); i++ {
  164. accGetted, err := sdb.GetAccount(common.Idx(i))
  165. assert.Nil(t, err)
  166. assert.Equal(t, accounts[i], accGetted)
  167. }
  168. // try already existing idx and get error
  169. _, err = sdb.GetAccount(common.Idx(1)) // check that exist
  170. assert.Nil(t, err)
  171. _, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
  172. assert.NotNil(t, err)
  173. assert.Equal(t, ErrAccountAlreadyExists, err)
  174. _, err = sdb.MTGetProof(common.Idx(1))
  175. assert.Nil(t, err)
  176. // update accounts
  177. for i := 0; i < len(accounts); i++ {
  178. accounts[i].Nonce = accounts[i].Nonce + 1
  179. _, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
  180. assert.Nil(t, err)
  181. }
  182. a, err := sdb.GetAccount(common.Idx(1)) // check that account value has been updated
  183. assert.Nil(t, err)
  184. assert.Equal(t, accounts[1].Nonce, a.Nonce)
  185. }
  186. func TestCheckpoints(t *testing.T) {
  187. dir, err := ioutil.TempDir("", "sdb")
  188. require.Nil(t, err)
  189. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  190. assert.Nil(t, err)
  191. // create test accounts
  192. var accounts []*common.Account
  193. for i := 0; i < 10; i++ {
  194. accounts = append(accounts, newAccount(t, i))
  195. }
  196. // add test accounts
  197. for i := 0; i < len(accounts); i++ {
  198. _, err = sdb.CreateAccount(common.Idx(i), accounts[i])
  199. assert.Nil(t, err)
  200. }
  201. // do checkpoints and check that currentBatch is correct
  202. err = sdb.MakeCheckpoint()
  203. assert.Nil(t, err)
  204. cb, err := sdb.GetCurrentBatch()
  205. assert.Nil(t, err)
  206. assert.Equal(t, common.BatchNum(1), cb)
  207. for i := 1; i < 10; i++ {
  208. err = sdb.MakeCheckpoint()
  209. assert.Nil(t, err)
  210. cb, err = sdb.GetCurrentBatch()
  211. assert.Nil(t, err)
  212. assert.Equal(t, common.BatchNum(i+1), cb)
  213. }
  214. // printCheckpoints(t, sdb.path)
  215. // reset checkpoint
  216. err = sdb.Reset(3)
  217. assert.Nil(t, err)
  218. // check that reset can be repeated (as there exist the 'current' and
  219. // 'BatchNum3', from where the 'current' is a copy)
  220. err = sdb.Reset(3)
  221. require.Nil(t, err)
  222. // check that currentBatch is as expected after Reset
  223. cb, err = sdb.GetCurrentBatch()
  224. assert.Nil(t, err)
  225. assert.Equal(t, common.BatchNum(3), cb)
  226. // advance one checkpoint and check that currentBatch is fine
  227. err = sdb.MakeCheckpoint()
  228. assert.Nil(t, err)
  229. cb, err = sdb.GetCurrentBatch()
  230. assert.Nil(t, err)
  231. assert.Equal(t, common.BatchNum(4), cb)
  232. err = sdb.DeleteCheckpoint(common.BatchNum(9))
  233. assert.Nil(t, err)
  234. err = sdb.DeleteCheckpoint(common.BatchNum(10))
  235. assert.Nil(t, err)
  236. err = sdb.DeleteCheckpoint(common.BatchNum(9)) // does not exist, should return err
  237. assert.NotNil(t, err)
  238. err = sdb.DeleteCheckpoint(common.BatchNum(11)) // does not exist, should return err
  239. assert.NotNil(t, err)
  240. // Create a LocalStateDB from the initial StateDB
  241. dirLocal, err := ioutil.TempDir("", "ldb")
  242. require.Nil(t, err)
  243. ldb, err := NewLocalStateDB(dirLocal, sdb, TypeBatchBuilder, 32)
  244. assert.Nil(t, err)
  245. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  246. err = ldb.Reset(4, true)
  247. assert.Nil(t, err)
  248. // check that currentBatch is 4 after the Reset
  249. cb, err = ldb.GetCurrentBatch()
  250. assert.Nil(t, err)
  251. assert.Equal(t, common.BatchNum(4), cb)
  252. // advance one checkpoint in ldb
  253. err = ldb.MakeCheckpoint()
  254. assert.Nil(t, err)
  255. cb, err = ldb.GetCurrentBatch()
  256. assert.Nil(t, err)
  257. assert.Equal(t, common.BatchNum(5), cb)
  258. // Create a 2nd LocalStateDB from the initial StateDB
  259. dirLocal2, err := ioutil.TempDir("", "ldb2")
  260. require.Nil(t, err)
  261. ldb2, err := NewLocalStateDB(dirLocal2, sdb, TypeBatchBuilder, 32)
  262. assert.Nil(t, err)
  263. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  264. err = ldb2.Reset(4, true)
  265. assert.Nil(t, err)
  266. // check that currentBatch is 4 after the Reset
  267. cb, err = ldb2.GetCurrentBatch()
  268. assert.Nil(t, err)
  269. assert.Equal(t, common.BatchNum(4), cb)
  270. // advance one checkpoint in ldb2
  271. err = ldb2.MakeCheckpoint()
  272. assert.Nil(t, err)
  273. cb, err = ldb2.GetCurrentBatch()
  274. assert.Nil(t, err)
  275. assert.Equal(t, common.BatchNum(5), cb)
  276. debug := false
  277. if debug {
  278. printCheckpoints(t, sdb.path)
  279. printCheckpoints(t, ldb.path)
  280. printCheckpoints(t, ldb2.path)
  281. }
  282. }
  283. func printCheckpoints(t *testing.T, path string) {
  284. files, err := ioutil.ReadDir(path)
  285. assert.Nil(t, err)
  286. fmt.Println(path)
  287. for _, f := range files {
  288. fmt.Println(" " + f.Name())
  289. }
  290. }