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.

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