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.

575 lines
16 KiB

  1. package statedb
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/big"
  6. "os"
  7. "strconv"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/hermeznetwork/hermez-node/log"
  10. "github.com/iden3/go-merkletree"
  11. "github.com/iden3/go-merkletree/db"
  12. "github.com/iden3/go-merkletree/db/pebble"
  13. )
  14. // TODO(Edu): Document here how StateDB is kept consistent
  15. var (
  16. // ErrStateDBWithoutMT is used when a method that requires a MerkleTree
  17. // is called in a StateDB that does not have a MerkleTree defined
  18. ErrStateDBWithoutMT = errors.New("Can not call method to use MerkleTree in a StateDB without MerkleTree")
  19. // ErrAccountAlreadyExists is used when CreateAccount is called and the
  20. // Account already exists
  21. ErrAccountAlreadyExists = errors.New("Can not CreateAccount because Account already exists")
  22. // ErrToIdxNotFound is used when trying to get the ToIdx from ToEthAddr
  23. // or ToEthAddr&ToBJJ
  24. ErrToIdxNotFound = errors.New("ToIdx can not be found")
  25. // ErrGetIdxNoCase is used when trying to get the Idx from EthAddr &
  26. // BJJ with not compatible combination
  27. ErrGetIdxNoCase = errors.New("Can not get Idx due unexpected combination of ethereum Address & BabyJubJub PublicKey")
  28. // KeyCurrentBatch is used as key in the db to store the current BatchNum
  29. KeyCurrentBatch = []byte("k:currentbatch")
  30. // PrefixKeyIdx is the key prefix for idx in the db
  31. PrefixKeyIdx = []byte("i:")
  32. // PrefixKeyAccHash is the key prefix for account hash in the db
  33. PrefixKeyAccHash = []byte("h:")
  34. // PrefixKeyMT is the key prefix for merkle tree in the db
  35. PrefixKeyMT = []byte("m:")
  36. // PrefixKeyAddr is the key prefix for address in the db
  37. PrefixKeyAddr = []byte("a:")
  38. // PrefixKeyAddrBJJ is the key prefix for address-babyjubjub in the db
  39. PrefixKeyAddrBJJ = []byte("ab:")
  40. )
  41. const (
  42. // PathBatchNum defines the subpath of the Batch Checkpoint in the
  43. // subpath of the StateDB
  44. PathBatchNum = "/BatchNum"
  45. // PathCurrent defines the subpath of the current Batch in the subpath
  46. // of the StateDB
  47. PathCurrent = "/current"
  48. // TypeSynchronizer defines a StateDB used by the Synchronizer, that
  49. // generates the ExitTree when processing the txs
  50. TypeSynchronizer = "synchronizer"
  51. // TypeTxSelector defines a StateDB used by the TxSelector, without
  52. // computing ExitTree neither the ZKInputs
  53. TypeTxSelector = "txselector"
  54. // TypeBatchBuilder defines a StateDB used by the BatchBuilder, that
  55. // generates the ExitTree and the ZKInput when processing the txs
  56. TypeBatchBuilder = "batchbuilder"
  57. )
  58. // TypeStateDB determines the type of StateDB
  59. type TypeStateDB string
  60. // StateDB represents the StateDB object
  61. type StateDB struct {
  62. path string
  63. currentBatch common.BatchNum
  64. db *pebble.PebbleStorage
  65. mt *merkletree.MerkleTree
  66. typ TypeStateDB
  67. // idx holds the current Idx that the BatchBuilder is using
  68. idx common.Idx
  69. zki *common.ZKInputs
  70. i int // i is the current transaction index in the ZKInputs generation (zki)
  71. }
  72. // NewStateDB creates a new StateDB, allowing to use an in-memory or in-disk
  73. // storage
  74. func NewStateDB(path string, typ TypeStateDB, nLevels int) (*StateDB, error) {
  75. var sto *pebble.PebbleStorage
  76. var err error
  77. sto, err = pebble.NewPebbleStorage(path+PathCurrent, false)
  78. if err != nil {
  79. return nil, err
  80. }
  81. var mt *merkletree.MerkleTree = nil
  82. if typ == TypeSynchronizer || typ == TypeBatchBuilder {
  83. mt, err = merkletree.NewMerkleTree(sto.WithPrefix(PrefixKeyMT), nLevels)
  84. if err != nil {
  85. return nil, err
  86. }
  87. }
  88. if typ == TypeTxSelector && nLevels != 0 {
  89. return nil, fmt.Errorf("invalid StateDB parameters: StateDB type==TypeStateDB can not have nLevels!=0")
  90. }
  91. sdb := &StateDB{
  92. path: path,
  93. db: sto,
  94. mt: mt,
  95. typ: typ,
  96. }
  97. // load currentBatch
  98. sdb.currentBatch, err = sdb.GetCurrentBatch()
  99. if err != nil {
  100. return nil, err
  101. }
  102. // make reset (get checkpoint) at currentBatch
  103. err = sdb.reset(sdb.currentBatch, false)
  104. if err != nil {
  105. return nil, err
  106. }
  107. return sdb, nil
  108. }
  109. // DB returns the *pebble.PebbleStorage from the StateDB
  110. func (s *StateDB) DB() *pebble.PebbleStorage {
  111. return s.db
  112. }
  113. // GetCurrentBatch returns the current BatchNum stored in the StateDB
  114. func (s *StateDB) GetCurrentBatch() (common.BatchNum, error) {
  115. cbBytes, err := s.db.Get(KeyCurrentBatch)
  116. if err == db.ErrNotFound {
  117. return 0, nil
  118. }
  119. if err != nil {
  120. return 0, err
  121. }
  122. return common.BatchNumFromBytes(cbBytes)
  123. }
  124. // setCurrentBatch stores the current BatchNum in the StateDB
  125. func (s *StateDB) setCurrentBatch() error {
  126. tx, err := s.db.NewTx()
  127. if err != nil {
  128. return err
  129. }
  130. err = tx.Put(KeyCurrentBatch, s.currentBatch.Bytes())
  131. if err != nil {
  132. return err
  133. }
  134. if err := tx.Commit(); err != nil {
  135. return err
  136. }
  137. return nil
  138. }
  139. // MakeCheckpoint does a checkpoint at the given batchNum in the defined path. Internally this advances & stores the current BatchNum, and then stores a Checkpoint of the current state of the StateDB.
  140. func (s *StateDB) MakeCheckpoint() error {
  141. // advance currentBatch
  142. s.currentBatch++
  143. log.Debugw("Making StateDB checkpoint", "batch", s.currentBatch, "type", s.typ)
  144. checkpointPath := s.path + PathBatchNum + strconv.Itoa(int(s.currentBatch))
  145. err := s.setCurrentBatch()
  146. if err != nil {
  147. return err
  148. }
  149. // if checkpoint BatchNum already exist in disk, delete it
  150. if _, err := os.Stat(checkpointPath); !os.IsNotExist(err) {
  151. err := os.RemoveAll(checkpointPath)
  152. if err != nil {
  153. return err
  154. }
  155. } else if err != nil && !os.IsNotExist(err) {
  156. return err
  157. }
  158. // execute Checkpoint
  159. err = s.db.Pebble().Checkpoint(checkpointPath)
  160. if err != nil {
  161. return err
  162. }
  163. return nil
  164. }
  165. // DeleteCheckpoint removes if exist the checkpoint of the given batchNum
  166. func (s *StateDB) DeleteCheckpoint(batchNum common.BatchNum) error {
  167. checkpointPath := s.path + PathBatchNum + strconv.Itoa(int(batchNum))
  168. if _, err := os.Stat(checkpointPath); os.IsNotExist(err) {
  169. return fmt.Errorf("Checkpoint with batchNum %d does not exist in DB", batchNum)
  170. }
  171. return os.RemoveAll(checkpointPath)
  172. }
  173. func pebbleMakeCheckpoint(source, dest string) error {
  174. // Remove dest folder (if it exists) before doing the checkpoint
  175. if _, err := os.Stat(dest); !os.IsNotExist(err) {
  176. err := os.RemoveAll(dest)
  177. if err != nil {
  178. return err
  179. }
  180. } else if err != nil && !os.IsNotExist(err) {
  181. return err
  182. }
  183. sto, err := pebble.NewPebbleStorage(source, false)
  184. if err != nil {
  185. return err
  186. }
  187. defer func() {
  188. errClose := sto.Pebble().Close()
  189. if errClose != nil {
  190. log.Errorw("Pebble.Close", "err", errClose)
  191. }
  192. }()
  193. // execute Checkpoint
  194. err = sto.Pebble().Checkpoint(dest)
  195. if err != nil {
  196. return err
  197. }
  198. return nil
  199. }
  200. // Reset resets the StateDB to the checkpoint at the given batchNum. Reset
  201. // does not delete the checkpoints between old current and the new current,
  202. // those checkpoints will remain in the storage, and eventually will be
  203. // deleted when MakeCheckpoint overwrites them.
  204. func (s *StateDB) Reset(batchNum common.BatchNum) error {
  205. return s.reset(batchNum, true)
  206. }
  207. // reset resets the StateDB to the checkpoint at the given batchNum. Reset
  208. // does not delete the checkpoints between old current and the new current,
  209. // those checkpoints will remain in the storage, and eventually will be
  210. // deleted when MakeCheckpoint overwrites them. `closeCurrent` will close the
  211. // currently opened db before doing the reset.
  212. func (s *StateDB) reset(batchNum common.BatchNum, closeCurrent bool) error {
  213. checkpointPath := s.path + PathBatchNum + strconv.Itoa(int(batchNum))
  214. currentPath := s.path + PathCurrent
  215. if closeCurrent {
  216. if err := s.db.Pebble().Close(); err != nil {
  217. return err
  218. }
  219. }
  220. // remove 'current'
  221. err := os.RemoveAll(currentPath)
  222. if err != nil {
  223. return err
  224. }
  225. if batchNum == 0 {
  226. // if batchNum == 0, open the new fresh 'current'
  227. sto, err := pebble.NewPebbleStorage(currentPath, false)
  228. if err != nil {
  229. return err
  230. }
  231. s.db = sto
  232. s.idx = 255
  233. s.currentBatch = batchNum
  234. return nil
  235. }
  236. // copy 'BatchNumX' to 'current'
  237. err = pebbleMakeCheckpoint(checkpointPath, currentPath)
  238. if err != nil {
  239. return err
  240. }
  241. // open the new 'current'
  242. sto, err := pebble.NewPebbleStorage(currentPath, false)
  243. if err != nil {
  244. return err
  245. }
  246. s.db = sto
  247. // get currentBatch num
  248. s.currentBatch, err = s.GetCurrentBatch()
  249. if err != nil {
  250. return err
  251. }
  252. // idx is obtained from the statedb reset
  253. s.idx, err = s.getIdx()
  254. if err != nil {
  255. return err
  256. }
  257. if s.mt != nil {
  258. // open the MT for the current s.db
  259. mt, err := merkletree.NewMerkleTree(s.db.WithPrefix(PrefixKeyMT), s.mt.MaxLevels())
  260. if err != nil {
  261. return err
  262. }
  263. s.mt = mt
  264. }
  265. return nil
  266. }
  267. // GetAccount returns the account for the given Idx
  268. func (s *StateDB) GetAccount(idx common.Idx) (*common.Account, error) {
  269. return getAccountInTreeDB(s.db, idx)
  270. }
  271. // GetAccounts returns all the accounts in the db. Use for debugging pruposes
  272. // only.
  273. func (s *StateDB) GetAccounts() ([]common.Account, error) {
  274. idxDB := s.db.WithPrefix(PrefixKeyIdx)
  275. idxs := []common.Idx{}
  276. // NOTE: Current implementation of Iterate in the pebble interface is
  277. // not efficient, as it iterates over all keys. Improve it following
  278. // this example: https://github.com/cockroachdb/pebble/pull/923/files
  279. if err := idxDB.Iterate(func(k []byte, v []byte) (bool, error) {
  280. idx, err := common.IdxFromBytes(k)
  281. if err != nil {
  282. return false, err
  283. }
  284. idxs = append(idxs, idx)
  285. return true, nil
  286. }); err != nil {
  287. return nil, err
  288. }
  289. accs := []common.Account{}
  290. for i := range idxs {
  291. acc, err := s.GetAccount(idxs[i])
  292. if err != nil {
  293. return nil, err
  294. }
  295. accs = append(accs, *acc)
  296. }
  297. return accs, nil
  298. }
  299. // getAccountInTreeDB is abstracted from StateDB to be used from StateDB and
  300. // from ExitTree. GetAccount returns the account for the given Idx
  301. func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error) {
  302. idxBytes, err := idx.Bytes()
  303. if err != nil {
  304. return nil, err
  305. }
  306. vBytes, err := sto.Get(append(PrefixKeyIdx, idxBytes[:]...))
  307. if err != nil {
  308. return nil, err
  309. }
  310. accBytes, err := sto.Get(append(PrefixKeyAccHash, vBytes...))
  311. if err != nil {
  312. return nil, err
  313. }
  314. var b [32 * common.NLeafElems]byte
  315. copy(b[:], accBytes)
  316. account, err := common.AccountFromBytes(b)
  317. if err != nil {
  318. return nil, err
  319. }
  320. account.Idx = idx
  321. return account, nil
  322. }
  323. // CreateAccount creates a new Account in the StateDB for the given Idx. If
  324. // StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
  325. // MerkleTree, returning a CircomProcessorProof.
  326. func (s *StateDB) CreateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
  327. cpp, err := createAccountInTreeDB(s.db, s.mt, idx, account)
  328. if err != nil {
  329. return cpp, err
  330. }
  331. // store idx by EthAddr & BJJ
  332. err = s.setIdxByEthAddrBJJ(idx, account.EthAddr, account.PublicKey, account.TokenID)
  333. return cpp, err
  334. }
  335. // createAccountInTreeDB is abstracted from StateDB to be used from StateDB and
  336. // from ExitTree. Creates a new Account in the StateDB for the given Idx. If
  337. // StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
  338. // MerkleTree, returning a CircomProcessorProof.
  339. func createAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
  340. // store at the DB the key: v, and value: leaf.Bytes()
  341. v, err := account.HashValue()
  342. if err != nil {
  343. return nil, err
  344. }
  345. accountBytes, err := account.Bytes()
  346. if err != nil {
  347. return nil, err
  348. }
  349. // store the Leaf value
  350. tx, err := sto.NewTx()
  351. if err != nil {
  352. return nil, err
  353. }
  354. idxBytes, err := idx.Bytes()
  355. if err != nil {
  356. return nil, err
  357. }
  358. _, err = tx.Get(append(PrefixKeyIdx, idxBytes[:]...))
  359. if err != db.ErrNotFound {
  360. return nil, ErrAccountAlreadyExists
  361. }
  362. err = tx.Put(append(PrefixKeyAccHash, v.Bytes()...), accountBytes[:])
  363. if err != nil {
  364. return nil, err
  365. }
  366. err = tx.Put(append(PrefixKeyIdx, idxBytes[:]...), v.Bytes())
  367. if err != nil {
  368. return nil, err
  369. }
  370. if err := tx.Commit(); err != nil {
  371. return nil, err
  372. }
  373. if mt != nil {
  374. return mt.AddAndGetCircomProof(idx.BigInt(), v)
  375. }
  376. return nil, nil
  377. }
  378. // UpdateAccount updates the Account in the StateDB for the given Idx. If
  379. // StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
  380. // MerkleTree, returning a CircomProcessorProof.
  381. func (s *StateDB) UpdateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
  382. return updateAccountInTreeDB(s.db, s.mt, idx, account)
  383. }
  384. // updateAccountInTreeDB is abstracted from StateDB to be used from StateDB and
  385. // from ExitTree. Updates the Account in the StateDB for the given Idx. If
  386. // StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
  387. // MerkleTree, returning a CircomProcessorProof.
  388. func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
  389. // store at the DB the key: v, and value: account.Bytes()
  390. v, err := account.HashValue()
  391. if err != nil {
  392. return nil, err
  393. }
  394. accountBytes, err := account.Bytes()
  395. if err != nil {
  396. return nil, err
  397. }
  398. tx, err := sto.NewTx()
  399. if err != nil {
  400. return nil, err
  401. }
  402. err = tx.Put(append(PrefixKeyAccHash, v.Bytes()...), accountBytes[:])
  403. if err != nil {
  404. return nil, err
  405. }
  406. idxBytes, err := idx.Bytes()
  407. if err != nil {
  408. return nil, err
  409. }
  410. err = tx.Put(append(PrefixKeyIdx, idxBytes[:]...), v.Bytes())
  411. if err != nil {
  412. return nil, err
  413. }
  414. if err := tx.Commit(); err != nil {
  415. return nil, err
  416. }
  417. if mt != nil {
  418. return mt.Update(idx.BigInt(), v)
  419. }
  420. return nil, nil
  421. }
  422. // MTGetProof returns the CircomVerifierProof for a given Idx
  423. func (s *StateDB) MTGetProof(idx common.Idx) (*merkletree.CircomVerifierProof, error) {
  424. if s.mt == nil {
  425. return nil, ErrStateDBWithoutMT
  426. }
  427. return s.mt.GenerateCircomVerifierProof(idx.BigInt(), s.mt.Root())
  428. }
  429. // MTGetRoot returns the current root of the underlying Merkle Tree
  430. func (s *StateDB) MTGetRoot() *big.Int {
  431. return s.mt.Root().BigInt()
  432. }
  433. // LocalStateDB represents the local StateDB which allows to make copies from
  434. // the synchronizer StateDB, and is used by the tx-selector and the
  435. // batch-builder. LocalStateDB is an in-memory storage.
  436. type LocalStateDB struct {
  437. *StateDB
  438. synchronizerStateDB *StateDB
  439. }
  440. // NewLocalStateDB returns a new LocalStateDB connected to the given
  441. // synchronizerDB
  442. func NewLocalStateDB(path string, synchronizerDB *StateDB, typ TypeStateDB, nLevels int) (*LocalStateDB, error) {
  443. s, err := NewStateDB(path, typ, nLevels)
  444. if err != nil {
  445. return nil, err
  446. }
  447. return &LocalStateDB{
  448. s,
  449. synchronizerDB,
  450. }, nil
  451. }
  452. // Reset performs a reset in the LocaStateDB. If fromSynchronizer is true, it
  453. // gets the state from LocalStateDB.synchronizerStateDB for the given batchNum. If fromSynchronizer is false, get the state from LocalStateDB checkpoints.
  454. func (l *LocalStateDB) Reset(batchNum common.BatchNum, fromSynchronizer bool) error {
  455. if batchNum == 0 {
  456. l.idx = 0
  457. return nil
  458. }
  459. synchronizerCheckpointPath := l.synchronizerStateDB.path + PathBatchNum + strconv.Itoa(int(batchNum))
  460. checkpointPath := l.path + PathBatchNum + strconv.Itoa(int(batchNum))
  461. currentPath := l.path + PathCurrent
  462. if fromSynchronizer {
  463. // use checkpoint from SynchronizerStateDB
  464. if _, err := os.Stat(synchronizerCheckpointPath); os.IsNotExist(err) {
  465. // if synchronizerStateDB does not have checkpoint at batchNum, return err
  466. return fmt.Errorf("Checkpoint not exist in Synchronizer")
  467. }
  468. if err := l.db.Pebble().Close(); err != nil {
  469. return err
  470. }
  471. // remove 'current'
  472. err := os.RemoveAll(currentPath)
  473. if err != nil {
  474. return err
  475. }
  476. // copy synchronizer'BatchNumX' to 'current'
  477. err = pebbleMakeCheckpoint(synchronizerCheckpointPath, currentPath)
  478. if err != nil {
  479. return err
  480. }
  481. // copy synchronizer'BatchNumX' to 'BatchNumX'
  482. err = pebbleMakeCheckpoint(synchronizerCheckpointPath, checkpointPath)
  483. if err != nil {
  484. return err
  485. }
  486. // open the new 'current'
  487. sto, err := pebble.NewPebbleStorage(currentPath, false)
  488. if err != nil {
  489. return err
  490. }
  491. l.db = sto
  492. // get currentBatch num
  493. l.currentBatch, err = l.GetCurrentBatch()
  494. if err != nil {
  495. return err
  496. }
  497. // open the MT for the current s.db
  498. mt, err := merkletree.NewMerkleTree(l.db.WithPrefix(PrefixKeyMT), l.mt.MaxLevels())
  499. if err != nil {
  500. return err
  501. }
  502. l.mt = mt
  503. return nil
  504. }
  505. // use checkpoint from LocalStateDB
  506. return l.StateDB.reset(batchNum, true)
  507. }