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.

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