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.

459 lines
12 KiB

  1. package statedb
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "io/ioutil"
  6. "math/big"
  7. "os"
  8. "strings"
  9. "testing"
  10. ethCommon "github.com/ethereum/go-ethereum/common"
  11. ethCrypto "github.com/ethereum/go-ethereum/crypto"
  12. "github.com/hermeznetwork/hermez-node/common"
  13. "github.com/iden3/go-iden3-crypto/babyjub"
  14. "github.com/iden3/go-merkletree/db"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. )
  18. func newAccount(t *testing.T, i int) *common.Account {
  19. var sk babyjub.PrivateKey
  20. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  21. require.Nil(t, err)
  22. pk := sk.Public()
  23. key, err := ethCrypto.GenerateKey()
  24. require.Nil(t, err)
  25. address := ethCrypto.PubkeyToAddress(key.PublicKey)
  26. return &common.Account{
  27. Idx: common.Idx(256 + i),
  28. TokenID: common.TokenID(i),
  29. Nonce: common.Nonce(i),
  30. Balance: big.NewInt(1000),
  31. PublicKey: pk,
  32. EthAddr: address,
  33. }
  34. }
  35. func TestNewStateDBIntermediateState(t *testing.T) {
  36. dir, err := ioutil.TempDir("", "tmpdb")
  37. require.Nil(t, err)
  38. defer assert.Nil(t, os.RemoveAll(dir))
  39. sdb, err := NewStateDB(dir, TypeTxSelector, 0)
  40. assert.Nil(t, err)
  41. // test values
  42. k0 := []byte("testkey0")
  43. k1 := []byte("testkey1")
  44. v0 := []byte("testvalue0")
  45. v1 := []byte("testvalue1")
  46. // store some data
  47. tx, err := sdb.db.NewTx()
  48. assert.Nil(t, err)
  49. err = tx.Put(k0, v0)
  50. assert.Nil(t, err)
  51. err = tx.Commit()
  52. assert.Nil(t, err)
  53. v, err := sdb.db.Get(k0)
  54. assert.Nil(t, err)
  55. assert.Equal(t, v0, v)
  56. // call NewStateDB which should get the db at the last checkpoint state
  57. // executing a Reset (discarding the last 'testkey0'&'testvalue0' data)
  58. sdb, err = NewStateDB(dir, TypeTxSelector, 0)
  59. assert.Nil(t, err)
  60. v, err = sdb.db.Get(k0)
  61. assert.NotNil(t, err)
  62. assert.Equal(t, db.ErrNotFound, err)
  63. assert.Nil(t, v)
  64. // store the same data from the beginning that has ben lost since last NewStateDB
  65. tx, err = sdb.db.NewTx()
  66. assert.Nil(t, err)
  67. err = tx.Put(k0, v0)
  68. assert.Nil(t, err)
  69. err = tx.Commit()
  70. assert.Nil(t, err)
  71. v, err = sdb.db.Get(k0)
  72. assert.Nil(t, err)
  73. assert.Equal(t, v0, v)
  74. // make checkpoints with the current state
  75. bn, err := sdb.GetCurrentBatch()
  76. assert.Nil(t, err)
  77. assert.Equal(t, common.BatchNum(0), bn)
  78. err = sdb.MakeCheckpoint()
  79. assert.Nil(t, err)
  80. bn, err = sdb.GetCurrentBatch()
  81. assert.Nil(t, err)
  82. assert.Equal(t, common.BatchNum(1), bn)
  83. // write more data
  84. tx, err = sdb.db.NewTx()
  85. assert.Nil(t, err)
  86. err = tx.Put(k1, v1)
  87. assert.Nil(t, err)
  88. err = tx.Commit()
  89. assert.Nil(t, err)
  90. v, err = sdb.db.Get(k1)
  91. assert.Nil(t, err)
  92. assert.Equal(t, v1, v)
  93. // call NewStateDB which should get the db at the last checkpoint state
  94. // executing a Reset (discarding the last 'testkey1'&'testvalue1' data)
  95. sdb, err = NewStateDB(dir, TypeTxSelector, 0)
  96. assert.Nil(t, err)
  97. v, err = sdb.db.Get(k0)
  98. assert.Nil(t, err)
  99. assert.Equal(t, v0, v)
  100. v, err = sdb.db.Get(k1)
  101. assert.NotNil(t, err)
  102. assert.Equal(t, db.ErrNotFound, err)
  103. assert.Nil(t, v)
  104. }
  105. func TestStateDBWithoutMT(t *testing.T) {
  106. dir, err := ioutil.TempDir("", "tmpdb")
  107. require.Nil(t, err)
  108. defer assert.Nil(t, os.RemoveAll(dir))
  109. sdb, err := NewStateDB(dir, TypeTxSelector, 0)
  110. assert.Nil(t, err)
  111. // create test accounts
  112. var accounts []*common.Account
  113. for i := 0; i < 4; i++ {
  114. accounts = append(accounts, newAccount(t, i))
  115. }
  116. // get non-existing account, expecting an error
  117. unexistingAccount := common.Idx(1)
  118. _, err = sdb.GetAccount(unexistingAccount)
  119. assert.NotNil(t, err)
  120. assert.Equal(t, db.ErrNotFound, err)
  121. // add test accounts
  122. for i := 0; i < len(accounts); i++ {
  123. _, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
  124. assert.Nil(t, err)
  125. }
  126. for i := 0; i < len(accounts); i++ {
  127. existingAccount := accounts[i].Idx
  128. accGetted, err := sdb.GetAccount(existingAccount)
  129. assert.Nil(t, err)
  130. assert.Equal(t, accounts[i], accGetted)
  131. }
  132. // try already existing idx and get error
  133. existingAccount := common.Idx(256)
  134. _, err = sdb.GetAccount(existingAccount) // check that exist
  135. assert.Nil(t, err)
  136. _, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
  137. assert.NotNil(t, err)
  138. assert.Equal(t, ErrAccountAlreadyExists, err)
  139. // update accounts
  140. for i := 0; i < len(accounts); i++ {
  141. accounts[i].Nonce = accounts[i].Nonce + 1
  142. existingAccount = common.Idx(i)
  143. _, err = sdb.UpdateAccount(existingAccount, accounts[i])
  144. assert.Nil(t, err)
  145. }
  146. _, err = sdb.MTGetProof(common.Idx(1))
  147. assert.NotNil(t, err)
  148. assert.Equal(t, ErrStateDBWithoutMT, err)
  149. }
  150. func TestStateDBWithMT(t *testing.T) {
  151. dir, err := ioutil.TempDir("", "tmpdb")
  152. require.Nil(t, err)
  153. defer assert.Nil(t, os.RemoveAll(dir))
  154. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  155. assert.Nil(t, err)
  156. // create test accounts
  157. var accounts []*common.Account
  158. for i := 0; i < 20; i++ {
  159. accounts = append(accounts, newAccount(t, i))
  160. }
  161. // get non-existing account, expecting an error
  162. _, err = sdb.GetAccount(common.Idx(1))
  163. assert.NotNil(t, err)
  164. assert.Equal(t, db.ErrNotFound, err)
  165. // add test accounts
  166. for i := 0; i < len(accounts); i++ {
  167. _, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
  168. assert.Nil(t, err)
  169. }
  170. for i := 0; i < len(accounts); i++ {
  171. accGetted, err := sdb.GetAccount(accounts[i].Idx)
  172. assert.Nil(t, err)
  173. assert.Equal(t, accounts[i], accGetted)
  174. }
  175. // try already existing idx and get error
  176. _, err = sdb.GetAccount(common.Idx(256)) // check that exist
  177. assert.Nil(t, err)
  178. _, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
  179. assert.NotNil(t, err)
  180. assert.Equal(t, ErrAccountAlreadyExists, err)
  181. _, err = sdb.MTGetProof(common.Idx(256))
  182. assert.Nil(t, err)
  183. // update accounts
  184. for i := 0; i < len(accounts); i++ {
  185. accounts[i].Nonce = accounts[i].Nonce + 1
  186. _, err = sdb.UpdateAccount(accounts[i].Idx, accounts[i])
  187. assert.Nil(t, err)
  188. }
  189. a, err := sdb.GetAccount(common.Idx(256)) // check that account value has been updated
  190. assert.Nil(t, err)
  191. assert.Equal(t, accounts[0].Nonce, a.Nonce)
  192. }
  193. func TestCheckpoints(t *testing.T) {
  194. dir, err := ioutil.TempDir("", "sdb")
  195. require.Nil(t, err)
  196. defer assert.Nil(t, os.RemoveAll(dir))
  197. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  198. assert.Nil(t, err)
  199. // create test accounts
  200. var accounts []*common.Account
  201. for i := 0; i < 10; i++ {
  202. accounts = append(accounts, newAccount(t, i))
  203. }
  204. // add test accounts
  205. for i := 0; i < len(accounts); i++ {
  206. _, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
  207. assert.Nil(t, err)
  208. }
  209. // do checkpoints and check that currentBatch is correct
  210. err = sdb.MakeCheckpoint()
  211. assert.Nil(t, err)
  212. cb, err := sdb.GetCurrentBatch()
  213. assert.Nil(t, err)
  214. assert.Equal(t, common.BatchNum(1), cb)
  215. for i := 1; i < 10; i++ {
  216. err = sdb.MakeCheckpoint()
  217. assert.Nil(t, err)
  218. cb, err = sdb.GetCurrentBatch()
  219. assert.Nil(t, err)
  220. assert.Equal(t, common.BatchNum(i+1), cb)
  221. }
  222. // printCheckpoints(t, sdb.path)
  223. // reset checkpoint
  224. err = sdb.Reset(3)
  225. assert.Nil(t, err)
  226. // check that reset can be repeated (as there exist the 'current' and
  227. // 'BatchNum3', from where the 'current' is a copy)
  228. err = sdb.Reset(3)
  229. require.Nil(t, err)
  230. // check that currentBatch is as expected after Reset
  231. cb, err = sdb.GetCurrentBatch()
  232. assert.Nil(t, err)
  233. assert.Equal(t, common.BatchNum(3), cb)
  234. // advance one checkpoint and check that currentBatch is fine
  235. err = sdb.MakeCheckpoint()
  236. assert.Nil(t, err)
  237. cb, err = sdb.GetCurrentBatch()
  238. assert.Nil(t, err)
  239. assert.Equal(t, common.BatchNum(4), cb)
  240. err = sdb.DeleteCheckpoint(common.BatchNum(9))
  241. assert.Nil(t, err)
  242. err = sdb.DeleteCheckpoint(common.BatchNum(10))
  243. assert.Nil(t, err)
  244. err = sdb.DeleteCheckpoint(common.BatchNum(9)) // does not exist, should return err
  245. assert.NotNil(t, err)
  246. err = sdb.DeleteCheckpoint(common.BatchNum(11)) // does not exist, should return err
  247. assert.NotNil(t, err)
  248. // Create a LocalStateDB from the initial StateDB
  249. dirLocal, err := ioutil.TempDir("", "ldb")
  250. require.Nil(t, err)
  251. defer assert.Nil(t, os.RemoveAll(dirLocal))
  252. ldb, err := NewLocalStateDB(dirLocal, sdb, TypeBatchBuilder, 32)
  253. assert.Nil(t, err)
  254. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  255. err = ldb.Reset(4, true)
  256. assert.Nil(t, err)
  257. // check that currentBatch is 4 after the Reset
  258. cb, err = ldb.GetCurrentBatch()
  259. assert.Nil(t, err)
  260. assert.Equal(t, common.BatchNum(4), cb)
  261. // advance one checkpoint in ldb
  262. err = ldb.MakeCheckpoint()
  263. assert.Nil(t, err)
  264. cb, err = ldb.GetCurrentBatch()
  265. assert.Nil(t, err)
  266. assert.Equal(t, common.BatchNum(5), cb)
  267. // Create a 2nd LocalStateDB from the initial StateDB
  268. dirLocal2, err := ioutil.TempDir("", "ldb2")
  269. require.Nil(t, err)
  270. defer assert.Nil(t, os.RemoveAll(dirLocal2))
  271. ldb2, err := NewLocalStateDB(dirLocal2, sdb, TypeBatchBuilder, 32)
  272. assert.Nil(t, err)
  273. // get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
  274. err = ldb2.Reset(4, true)
  275. assert.Nil(t, err)
  276. // check that currentBatch is 4 after the Reset
  277. cb, err = ldb2.GetCurrentBatch()
  278. assert.Nil(t, err)
  279. assert.Equal(t, common.BatchNum(4), cb)
  280. // advance one checkpoint in ldb2
  281. err = ldb2.MakeCheckpoint()
  282. assert.Nil(t, err)
  283. cb, err = ldb2.GetCurrentBatch()
  284. assert.Nil(t, err)
  285. assert.Equal(t, common.BatchNum(5), cb)
  286. debug := false
  287. if debug {
  288. printCheckpoints(t, sdb.path)
  289. printCheckpoints(t, ldb.path)
  290. printCheckpoints(t, ldb2.path)
  291. }
  292. }
  293. func TestStateDBGetAccounts(t *testing.T) {
  294. dir, err := ioutil.TempDir("", "tmpdb")
  295. require.Nil(t, err)
  296. sdb, err := NewStateDB(dir, TypeTxSelector, 0)
  297. assert.Nil(t, err)
  298. // create test accounts
  299. var accounts []common.Account
  300. for i := 0; i < 16; i++ {
  301. account := newAccount(t, i)
  302. accounts = append(accounts, *account)
  303. }
  304. // add test accounts
  305. for i := range accounts {
  306. _, err = sdb.CreateAccount(accounts[i].Idx, &accounts[i])
  307. require.Nil(t, err)
  308. }
  309. dbAccounts, err := sdb.GetAccounts()
  310. require.Nil(t, err)
  311. assert.Equal(t, accounts, dbAccounts)
  312. }
  313. func printCheckpoints(t *testing.T, path string) {
  314. files, err := ioutil.ReadDir(path)
  315. assert.Nil(t, err)
  316. fmt.Println(path)
  317. for _, f := range files {
  318. fmt.Println(" " + f.Name())
  319. }
  320. }
  321. func bigFromStr(h string, u int) *big.Int {
  322. if u == 16 {
  323. h = strings.TrimPrefix(h, "0x")
  324. }
  325. b, ok := new(big.Int).SetString(h, u)
  326. if !ok {
  327. panic("bigFromStr err")
  328. }
  329. return b
  330. }
  331. func TestCheckAccountsTreeTestVectors(t *testing.T) {
  332. dir, err := ioutil.TempDir("", "tmpdb")
  333. require.Nil(t, err)
  334. defer assert.Nil(t, os.RemoveAll(dir))
  335. sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
  336. require.Nil(t, err)
  337. ay0 := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(253), nil), big.NewInt(1))
  338. // test value from js version (compatibility-canary)
  339. assert.Equal(t, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", (hex.EncodeToString(ay0.Bytes())))
  340. bjj0, err := babyjub.PointFromSignAndY(true, ay0)
  341. require.Nil(t, err)
  342. ay1 := bigFromStr("00", 16)
  343. bjj1, err := babyjub.PointFromSignAndY(false, ay1)
  344. require.Nil(t, err)
  345. ay2 := bigFromStr("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7", 16)
  346. bjj2, err := babyjub.PointFromSignAndY(false, ay2)
  347. require.Nil(t, err)
  348. ay3 := bigFromStr("0x10", 16) // 0x10=16
  349. bjj3, err := babyjub.PointFromSignAndY(false, ay3)
  350. require.Nil(t, err)
  351. accounts := []*common.Account{
  352. {
  353. Idx: 1,
  354. TokenID: 0xFFFFFFFF,
  355. PublicKey: (*babyjub.PublicKey)(bjj0),
  356. EthAddr: ethCommon.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
  357. Nonce: common.Nonce(0xFFFFFFFFFF),
  358. Balance: bigFromStr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16),
  359. },
  360. {
  361. Idx: 100,
  362. TokenID: 0,
  363. PublicKey: (*babyjub.PublicKey)(bjj1),
  364. EthAddr: ethCommon.HexToAddress("0x00"),
  365. Nonce: common.Nonce(0),
  366. Balance: bigFromStr("0", 10),
  367. },
  368. {
  369. Idx: 0xFFFFFFFFFFFF,
  370. TokenID: 3,
  371. PublicKey: (*babyjub.PublicKey)(bjj2),
  372. EthAddr: ethCommon.HexToAddress("0xA3C88ac39A76789437AED31B9608da72e1bbfBF9"),
  373. Nonce: common.Nonce(129),
  374. Balance: bigFromStr("42000000000000000000", 10),
  375. },
  376. {
  377. Idx: 10000,
  378. TokenID: 1000,
  379. PublicKey: (*babyjub.PublicKey)(bjj3),
  380. EthAddr: ethCommon.HexToAddress("0x64"),
  381. Nonce: common.Nonce(1900),
  382. Balance: bigFromStr("14000000000000000000", 10),
  383. },
  384. }
  385. for i := 0; i < len(accounts); i++ {
  386. _, err = accounts[i].HashValue()
  387. require.Nil(t, err)
  388. _, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
  389. require.Nil(t, err)
  390. }
  391. // root value generated by js version:
  392. assert.Equal(t, "17298264051379321456969039521810887093935433569451713402227686942080129181291", sdb.mt.Root().BigInt().String())
  393. }