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.

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