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.

352 lines
9.2 KiB

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