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.

338 lines
9.4 KiB

  1. package statedb
  2. import (
  3. "math/big"
  4. "github.com/hermeznetwork/hermez-node/common"
  5. "github.com/iden3/go-iden3-crypto/poseidon"
  6. "github.com/iden3/go-merkletree"
  7. "github.com/iden3/go-merkletree/db"
  8. "github.com/iden3/go-merkletree/db/memory"
  9. )
  10. // keyidx is used as key in the db to store the current Idx
  11. var keyidx = []byte("idx")
  12. // FUTURE This will be used from common once pending PR is merged
  13. type ExitInfo struct {
  14. Idx *common.Idx
  15. Proof *merkletree.CircomVerifierProof
  16. Nullifier *big.Int
  17. Balance *big.Int
  18. }
  19. // ProcessTxs process the given L1Txs & L2Txs applying the needed updates to
  20. // the StateDB depending on the transaction Type. Returns the common.ZKInputs
  21. // to generate the SnarkProof later used by the BatchBuilder, and if
  22. // cmpExitTree is set to true, returns common.ExitTreeLeaf that is later used
  23. // by the Synchronizer to update the HistoryDB.
  24. func (s *StateDB) ProcessTxs(cmpExitTree bool, l1usertxs, l1coordinatortxs []*common.L1Tx, l2txs []*common.L2Tx) (*common.ZKInputs, []*ExitInfo, error) {
  25. var err error
  26. var exitTree *merkletree.MerkleTree
  27. exits := make(map[common.Idx]common.Account)
  28. // TBD if ExitTree is only in memory or stored in disk, for the moment
  29. // only needed in memory
  30. exitTree, err = merkletree.NewMerkleTree(memory.NewMemoryStorage(), s.mt.MaxLevels())
  31. if err != nil {
  32. return nil, nil, err
  33. }
  34. for _, tx := range l1coordinatortxs {
  35. exitIdx, exitAccount, err := s.processL1Tx(exitTree, tx)
  36. if err != nil {
  37. return nil, nil, err
  38. }
  39. if exitIdx != nil && cmpExitTree {
  40. exits[*exitIdx] = *exitAccount
  41. }
  42. }
  43. for _, tx := range l1usertxs {
  44. exitIdx, exitAccount, err := s.processL1Tx(exitTree, tx)
  45. if err != nil {
  46. return nil, nil, err
  47. }
  48. if exitIdx != nil && cmpExitTree {
  49. exits[*exitIdx] = *exitAccount
  50. }
  51. }
  52. for _, tx := range l2txs {
  53. exitIdx, exitAccount, err := s.processL2Tx(exitTree, tx)
  54. if err != nil {
  55. return nil, nil, err
  56. }
  57. if exitIdx != nil && cmpExitTree {
  58. exits[*exitIdx] = *exitAccount
  59. }
  60. }
  61. if !cmpExitTree {
  62. return nil, nil, nil
  63. }
  64. // once all txs processed (exitTree root frozen), for each leaf
  65. // generate ExitInfo data
  66. var exitInfos []*ExitInfo
  67. for exitIdx, exitAccount := range exits {
  68. // 0. generate MerkleProof
  69. p, err := exitTree.GenerateCircomVerifierProof(exitIdx.BigInt(), nil)
  70. if err != nil {
  71. return nil, nil, err
  72. }
  73. // 1. compute nullifier
  74. exitAccStateValue, err := exitAccount.HashValue()
  75. if err != nil {
  76. return nil, nil, err
  77. }
  78. nullifier, err := poseidon.Hash([]*big.Int{
  79. exitAccStateValue,
  80. big.NewInt(int64(s.currentBatch)),
  81. exitTree.Root().BigInt(),
  82. })
  83. if err != nil {
  84. return nil, nil, err
  85. }
  86. // 2. generate ExitInfo
  87. ei := &ExitInfo{
  88. Idx: &exitIdx,
  89. Proof: p,
  90. Nullifier: nullifier,
  91. Balance: exitAccount.Balance,
  92. }
  93. exitInfos = append(exitInfos, ei)
  94. }
  95. // return exitInfos, so Synchronizer will be able to store it into
  96. // HistoryDB for the concrete BatchNum
  97. return nil, exitInfos, nil
  98. }
  99. // processL1Tx process the given L1Tx applying the needed updates to the
  100. // StateDB depending on the transaction Type.
  101. func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx) (*common.Idx, *common.Account, error) {
  102. switch tx.Type {
  103. case common.TxTypeForceTransfer, common.TxTypeTransfer:
  104. // go to the MT account of sender and receiver, and update balance
  105. // & nonce
  106. err := s.applyTransfer(tx.Tx())
  107. if err != nil {
  108. return nil, nil, err
  109. }
  110. case common.TxTypeCreateAccountDeposit:
  111. // add new account to the MT, update balance of the MT account
  112. err := s.applyCreateAccount(tx)
  113. if err != nil {
  114. return nil, nil, err
  115. }
  116. case common.TxTypeDeposit:
  117. // update balance of the MT account
  118. err := s.applyDeposit(tx, false)
  119. if err != nil {
  120. return nil, nil, err
  121. }
  122. case common.TxTypeDepositTransfer:
  123. // update balance in MT account, update balance & nonce of sender
  124. // & receiver
  125. err := s.applyDeposit(tx, true)
  126. if err != nil {
  127. return nil, nil, err
  128. }
  129. case common.TxTypeCreateAccountDepositTransfer:
  130. // add new account to the merkletree, update balance in MT account,
  131. // update balance & nonce of sender & receiver
  132. err := s.applyCreateAccount(tx)
  133. if err != nil {
  134. return nil, nil, err
  135. }
  136. err = s.applyTransfer(tx.Tx())
  137. if err != nil {
  138. return nil, nil, err
  139. }
  140. case common.TxTypeExit:
  141. // execute exit flow
  142. exitAccount, err := s.applyExit(exitTree, tx.Tx())
  143. if err != nil {
  144. return nil, nil, err
  145. }
  146. return &tx.FromIdx, exitAccount, nil
  147. default:
  148. }
  149. return nil, nil, nil
  150. }
  151. // processL2Tx process the given L2Tx applying the needed updates to
  152. // the StateDB depending on the transaction Type.
  153. func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.L2Tx) (*common.Idx, *common.Account, error) {
  154. switch tx.Type {
  155. case common.TxTypeTransfer:
  156. // go to the MT account of sender and receiver, and update
  157. // balance & nonce
  158. err := s.applyTransfer(tx.Tx())
  159. if err != nil {
  160. return nil, nil, err
  161. }
  162. case common.TxTypeExit:
  163. // execute exit flow
  164. exitAccount, err := s.applyExit(exitTree, tx.Tx())
  165. if err != nil {
  166. return nil, nil, err
  167. }
  168. return &tx.FromIdx, exitAccount, nil
  169. default:
  170. }
  171. return nil, nil, nil
  172. }
  173. // applyCreateAccount creates a new account in the account of the depositer, it
  174. // stores the deposit value
  175. func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
  176. account := &common.Account{
  177. TokenID: tx.TokenID,
  178. Nonce: 0,
  179. Balance: tx.LoadAmount,
  180. PublicKey: tx.FromBJJ,
  181. EthAddr: tx.FromEthAddr,
  182. }
  183. _, err := s.CreateAccount(common.Idx(s.idx+1), account)
  184. if err != nil {
  185. return err
  186. }
  187. s.idx = s.idx + 1
  188. return s.setIdx(s.idx)
  189. }
  190. // applyDeposit updates the balance in the account of the depositer, if
  191. // andTransfer parameter is set to true, the method will also apply the
  192. // Transfer of the L1Tx/DepositTransfer
  193. func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
  194. // deposit the tx.LoadAmount into the sender account
  195. accSender, err := s.GetAccount(tx.FromIdx)
  196. if err != nil {
  197. return err
  198. }
  199. accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
  200. // in case that the tx is a L1Tx>DepositTransfer
  201. if transfer {
  202. accReceiver, err := s.GetAccount(tx.ToIdx)
  203. if err != nil {
  204. return err
  205. }
  206. // substract amount to the sender
  207. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
  208. // add amount to the receiver
  209. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
  210. // update receiver account in localStateDB
  211. _, err = s.UpdateAccount(tx.ToIdx, accReceiver)
  212. if err != nil {
  213. return err
  214. }
  215. }
  216. // update sender account in localStateDB
  217. _, err = s.UpdateAccount(tx.FromIdx, accSender)
  218. if err != nil {
  219. return err
  220. }
  221. return nil
  222. }
  223. // applyTransfer updates the balance & nonce in the account of the sender, and
  224. // the balance in the account of the receiver
  225. func (s *StateDB) applyTransfer(tx *common.Tx) error {
  226. // get sender and receiver accounts from localStateDB
  227. accSender, err := s.GetAccount(tx.FromIdx)
  228. if err != nil {
  229. return err
  230. }
  231. accReceiver, err := s.GetAccount(tx.ToIdx)
  232. if err != nil {
  233. return err
  234. }
  235. // increment nonce
  236. accSender.Nonce++
  237. // substract amount to the sender
  238. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
  239. // add amount to the receiver
  240. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
  241. // update receiver account in localStateDB
  242. _, err = s.UpdateAccount(tx.ToIdx, accReceiver)
  243. if err != nil {
  244. return err
  245. }
  246. // update sender account in localStateDB
  247. _, err = s.UpdateAccount(tx.FromIdx, accSender)
  248. if err != nil {
  249. return err
  250. }
  251. return nil
  252. }
  253. func (s *StateDB) applyExit(exitTree *merkletree.MerkleTree, tx *common.Tx) (*common.Account, error) {
  254. // 0. substract tx.Amount from current Account in StateMT
  255. // add the tx.Amount into the Account (tx.FromIdx) in the ExitMT
  256. acc, err := s.GetAccount(tx.FromIdx)
  257. if err != nil {
  258. return nil, err
  259. }
  260. acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount)
  261. _, err = s.UpdateAccount(tx.FromIdx, acc)
  262. if err != nil {
  263. return nil, err
  264. }
  265. exitAccount, err := getAccountInTreeDB(exitTree.DB(), tx.FromIdx)
  266. if err == db.ErrNotFound {
  267. // 1a. if idx does not exist in exitTree:
  268. // add new leaf 'ExitTreeLeaf', where ExitTreeLeaf.Balance = exitAmount (exitAmount=tx.Amount)
  269. exitAccount := &common.Account{
  270. TokenID: acc.TokenID,
  271. Nonce: common.Nonce(1),
  272. Balance: tx.Amount,
  273. PublicKey: acc.PublicKey,
  274. EthAddr: acc.EthAddr,
  275. }
  276. _, err = createAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
  277. return exitAccount, err
  278. } else if err != nil {
  279. return exitAccount, err
  280. }
  281. // 1b. if idx already exist in exitTree:
  282. // update account, where account.Balance += exitAmount
  283. exitAccount.Balance = new(big.Int).Add(exitAccount.Balance, tx.Amount)
  284. _, err = updateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
  285. return exitAccount, err
  286. }
  287. // getIdx returns the stored Idx from the localStateDB, which is the last Idx
  288. // used for an Account in the localStateDB.
  289. func (s *StateDB) getIdx() (common.Idx, error) {
  290. idxBytes, err := s.DB().Get(keyidx)
  291. if err == db.ErrNotFound {
  292. return 0, nil
  293. }
  294. if err != nil {
  295. return 0, err
  296. }
  297. return common.IdxFromBytes(idxBytes[:4])
  298. }
  299. // setIdx stores Idx in the localStateDB
  300. func (s *StateDB) setIdx(idx common.Idx) error {
  301. tx, err := s.DB().NewTx()
  302. if err != nil {
  303. return err
  304. }
  305. tx.Put(keyidx, idx.Bytes())
  306. if err := tx.Commit(); err != nil {
  307. return err
  308. }
  309. return nil
  310. }