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.

222 lines
5.7 KiB

  1. package statedb
  2. import (
  3. "math/big"
  4. "github.com/hermeznetwork/hermez-node/common"
  5. "github.com/iden3/go-merkletree/db"
  6. )
  7. // keyidx is used as key in the db to store the current Idx
  8. var keyidx = []byte("idx")
  9. // ProcessTxs process the given L1Txs & L2Txs applying the needed updates
  10. // to the StateDB depending on the transaction Type. Returns the
  11. // common.ZKInputs to generate the SnarkProof later used by the BatchBuilder,
  12. // and returns common.ExitTreeLeaf that is later used by the Synchronizer to
  13. // update the HistoryDB.
  14. func (s *StateDB) ProcessTxs(l1usertxs, l1coordinatortxs []*common.L1Tx, l2txs []*common.L2Tx) (*common.ZKInputs, []*common.ExitTreeLeaf, error) {
  15. for _, tx := range l1usertxs {
  16. err := s.processL1Tx(tx)
  17. if err != nil {
  18. return nil, nil, err
  19. }
  20. }
  21. for _, tx := range l1coordinatortxs {
  22. err := s.processL1Tx(tx)
  23. if err != nil {
  24. return nil, nil, err
  25. }
  26. }
  27. for _, tx := range l2txs {
  28. err := s.processL2Tx(tx)
  29. if err != nil {
  30. return nil, nil, err
  31. }
  32. }
  33. return nil, nil, nil
  34. }
  35. // processL2Tx process the given L2Tx applying the needed updates to
  36. // the StateDB depending on the transaction Type.
  37. func (s *StateDB) processL2Tx(tx *common.L2Tx) error {
  38. switch tx.Type {
  39. case common.TxTypeTransfer:
  40. // go to the MT account of sender and receiver, and update
  41. // balance & nonce
  42. err := s.applyTransfer(tx.Tx())
  43. if err != nil {
  44. return err
  45. }
  46. case common.TxTypeExit:
  47. // execute exit flow
  48. default:
  49. }
  50. return nil
  51. }
  52. // processL1Tx process the given L1Tx applying the needed updates to the
  53. // StateDB depending on the transaction Type.
  54. func (s *StateDB) processL1Tx(tx *common.L1Tx) error {
  55. switch tx.Type {
  56. case common.TxTypeForceTransfer, common.TxTypeTransfer:
  57. // go to the MT account of sender and receiver, and update balance
  58. // & nonce
  59. err := s.applyTransfer(tx.Tx())
  60. if err != nil {
  61. return err
  62. }
  63. case common.TxTypeCreateAccountDeposit:
  64. // add new account to the MT, update balance of the MT account
  65. err := s.applyCreateAccount(tx)
  66. if err != nil {
  67. return err
  68. }
  69. case common.TxTypeDeposit:
  70. // update balance of the MT account
  71. err := s.applyDeposit(tx, false)
  72. if err != nil {
  73. return err
  74. }
  75. case common.TxTypeDepositTransfer:
  76. // update balance in MT account, update balance & nonce of sender
  77. // & receiver
  78. err := s.applyDeposit(tx, true)
  79. if err != nil {
  80. return err
  81. }
  82. case common.TxTypeCreateAccountDepositTransfer:
  83. // add new account to the merkletree, update balance in MT account,
  84. // update balance & nonce of sender & receiver
  85. err := s.applyCreateAccount(tx)
  86. if err != nil {
  87. return err
  88. }
  89. err = s.applyTransfer(tx.Tx())
  90. if err != nil {
  91. return err
  92. }
  93. case common.TxTypeExit:
  94. // execute exit flow
  95. default:
  96. }
  97. return nil
  98. }
  99. // applyCreateAccount creates a new account in the account of the depositer, it
  100. // stores the deposit value
  101. func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
  102. account := &common.Account{
  103. TokenID: tx.TokenID,
  104. Nonce: 0,
  105. Balance: tx.LoadAmount,
  106. PublicKey: tx.FromBJJ,
  107. EthAddr: tx.FromEthAddr,
  108. }
  109. _, err := s.CreateAccount(common.Idx(s.idx+1), account)
  110. if err != nil {
  111. return err
  112. }
  113. s.idx = s.idx + 1
  114. return s.setIdx(s.idx)
  115. }
  116. // applyDeposit updates the balance in the account of the depositer, if
  117. // andTransfer parameter is set to true, the method will also apply the
  118. // Transfer of the L1Tx/DepositTransfer
  119. func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
  120. // deposit the tx.LoadAmount into the sender account
  121. accSender, err := s.GetAccount(tx.FromIdx)
  122. if err != nil {
  123. return err
  124. }
  125. accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
  126. // in case that the tx is a L1Tx>DepositTransfer
  127. if transfer {
  128. accReceiver, err := s.GetAccount(tx.ToIdx)
  129. if err != nil {
  130. return err
  131. }
  132. // substract amount to the sender
  133. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
  134. // add amount to the receiver
  135. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
  136. // update receiver account in localStateDB
  137. _, err = s.UpdateAccount(tx.ToIdx, accReceiver)
  138. if err != nil {
  139. return err
  140. }
  141. }
  142. // update sender account in localStateDB
  143. _, err = s.UpdateAccount(tx.FromIdx, accSender)
  144. if err != nil {
  145. return err
  146. }
  147. return nil
  148. }
  149. // applyTransfer updates the balance & nonce in the account of the sender, and
  150. // the balance in the account of the receiver
  151. func (s *StateDB) applyTransfer(tx *common.Tx) error {
  152. // get sender and receiver accounts from localStateDB
  153. accSender, err := s.GetAccount(tx.FromIdx)
  154. if err != nil {
  155. return err
  156. }
  157. accReceiver, err := s.GetAccount(tx.ToIdx)
  158. if err != nil {
  159. return err
  160. }
  161. // increment nonce
  162. accSender.Nonce++
  163. // substract amount to the sender
  164. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
  165. // add amount to the receiver
  166. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
  167. // update receiver account in localStateDB
  168. _, err = s.UpdateAccount(tx.ToIdx, accReceiver)
  169. if err != nil {
  170. return err
  171. }
  172. // update sender account in localStateDB
  173. _, err = s.UpdateAccount(tx.FromIdx, accSender)
  174. if err != nil {
  175. return err
  176. }
  177. return nil
  178. }
  179. // getIdx returns the stored Idx from the localStateDB, which is the last Idx
  180. // used for an Account in the localStateDB.
  181. func (s *StateDB) getIdx() (common.Idx, error) {
  182. idxBytes, err := s.DB().Get(keyidx)
  183. if err == db.ErrNotFound {
  184. return 0, nil
  185. }
  186. if err != nil {
  187. return 0, err
  188. }
  189. return common.IdxFromBytes(idxBytes[:4])
  190. }
  191. // setIdx stores Idx in the localStateDB
  192. func (s *StateDB) setIdx(idx common.Idx) error {
  193. tx, err := s.DB().NewTx()
  194. if err != nil {
  195. return err
  196. }
  197. tx.Put(keyidx, idx.Bytes())
  198. if err := tx.Commit(); err != nil {
  199. return err
  200. }
  201. return nil
  202. }