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.

264 lines
7.2 KiB

  1. package batchbuilder
  2. import (
  3. "encoding/binary"
  4. "math/big"
  5. ethCommon "github.com/ethereum/go-ethereum/common"
  6. "github.com/hermeznetwork/hermez-node/common"
  7. "github.com/hermeznetwork/hermez-node/db/statedb"
  8. "github.com/iden3/go-merkletree/db"
  9. )
  10. // KEYIDX is used as key in the db to store the current Idx
  11. var KEYIDX = []byte("idx")
  12. // ConfigCircuit contains the circuit configuration
  13. type ConfigCircuit struct {
  14. TxsMax uint64
  15. L1TxsMax uint64
  16. SMTLevelsMax uint64
  17. }
  18. // BatchBuilder implements the batch builder type, which contains the
  19. // functionalities
  20. type BatchBuilder struct {
  21. // idx holds the current Idx that the BatchBuilder is using
  22. idx uint64
  23. localStateDB *statedb.LocalStateDB
  24. configCircuits []ConfigCircuit
  25. }
  26. // ConfigBatch contains the batch configuration
  27. type ConfigBatch struct {
  28. ForgerAddress ethCommon.Address
  29. }
  30. // NewBatchBuilder constructs a new BatchBuilder, and executes the bb.Reset
  31. // method
  32. func NewBatchBuilder(dbpath string, synchronizerStateDB *statedb.StateDB, configCircuits []ConfigCircuit, batchNum uint64, nLevels uint64) (*BatchBuilder, error) {
  33. localStateDB, err := statedb.NewLocalStateDB(dbpath, synchronizerStateDB, true, int(nLevels))
  34. if err != nil {
  35. return nil, err
  36. }
  37. bb := BatchBuilder{
  38. localStateDB: localStateDB,
  39. configCircuits: configCircuits,
  40. }
  41. err = bb.Reset(batchNum, true)
  42. return &bb, err
  43. }
  44. // Reset tells the BatchBuilder to reset it's internal state to the required
  45. // `batchNum`. If `fromSynchronizer` is true, the BatchBuilder must take a
  46. // copy of the rollup state from the Synchronizer at that `batchNum`, otherwise
  47. // it can just roll back the internal copy.
  48. func (bb *BatchBuilder) Reset(batchNum uint64, fromSynchronizer bool) error {
  49. if batchNum == 0 {
  50. bb.idx = 0
  51. return nil
  52. }
  53. err := bb.localStateDB.Reset(batchNum, fromSynchronizer)
  54. if err != nil {
  55. return err
  56. }
  57. // idx is obtained from the statedb reset
  58. bb.idx, err = bb.getIdx()
  59. return err
  60. }
  61. // BuildBatch takes the transactions and returns the common.ZKInputs of the next batch
  62. func (bb *BatchBuilder) BuildBatch(configBatch ConfigBatch, l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.PoolL2Tx, tokenIDs []common.TokenID) (*common.ZKInputs, error) {
  63. for _, tx := range l1usertxs {
  64. err := bb.processL1Tx(tx)
  65. if err != nil {
  66. return nil, err
  67. }
  68. }
  69. for _, tx := range l1coordinatortxs {
  70. err := bb.processL1Tx(tx)
  71. if err != nil {
  72. return nil, err
  73. }
  74. }
  75. for _, tx := range l2txs {
  76. switch tx.Type {
  77. case common.TxTypeTransfer:
  78. // go to the MT account of sender and receiver, and update
  79. // balance & nonce
  80. err := bb.applyTransfer(tx.Tx)
  81. if err != nil {
  82. return nil, err
  83. }
  84. case common.TxTypeExit:
  85. // execute exit flow
  86. default:
  87. }
  88. }
  89. return nil, nil
  90. }
  91. func (bb *BatchBuilder) processL1Tx(tx common.L1Tx) error {
  92. switch tx.Type {
  93. case common.TxTypeForceTransfer, common.TxTypeTransfer:
  94. // go to the MT account of sender and receiver, and update balance
  95. // & nonce
  96. err := bb.applyTransfer(tx.Tx)
  97. if err != nil {
  98. return err
  99. }
  100. case common.TxTypeCreateAccountDeposit:
  101. // add new account to the MT, update balance of the MT account
  102. err := bb.applyCreateAccount(tx)
  103. if err != nil {
  104. return err
  105. }
  106. case common.TxTypeDeposit: // TODO check if this type will ever exist, or will be TxTypeDepositAndTransfer with transfer 0 value
  107. // update balance of the MT account
  108. err := bb.applyDeposit(tx, false)
  109. if err != nil {
  110. return err
  111. }
  112. case common.TxTypeDepositAndTransfer:
  113. // update balance in MT account, update balance & nonce of sender
  114. // & receiver
  115. err := bb.applyDeposit(tx, true)
  116. if err != nil {
  117. return err
  118. }
  119. case common.TxTypeCreateAccountDepositAndTransfer:
  120. // add new account to the merkletree, update balance in MT account,
  121. // update balance & nonce of sender & receiver
  122. err := bb.applyCreateAccount(tx)
  123. if err != nil {
  124. return err
  125. }
  126. err = bb.applyTransfer(tx.Tx)
  127. if err != nil {
  128. return err
  129. }
  130. case common.TxTypeExit:
  131. // execute exit flow
  132. default:
  133. }
  134. return nil
  135. }
  136. // applyCreateAccount creates a new account in the account of the depositer, it
  137. // stores the deposit value
  138. func (bb *BatchBuilder) applyCreateAccount(tx common.L1Tx) error {
  139. account := &common.Account{
  140. TokenID: tx.TokenID,
  141. Nonce: 0,
  142. Balance: tx.LoadAmount,
  143. PublicKey: &tx.FromBJJ,
  144. EthAddr: tx.FromEthAddr,
  145. }
  146. err := bb.localStateDB.CreateAccount(common.Idx(bb.idx+1), account)
  147. if err != nil {
  148. return err
  149. }
  150. bb.idx = bb.idx + 1
  151. return bb.setIdx(bb.idx)
  152. }
  153. // applyDeposit updates the balance in the account of the depositer, if
  154. // andTransfer parameter is set to true, the method will also apply the
  155. // Transfer of the L1Tx/DepositAndTransfer
  156. func (bb *BatchBuilder) applyDeposit(tx common.L1Tx, transfer bool) error {
  157. // deposit the tx.LoadAmount into the sender account
  158. accSender, err := bb.localStateDB.GetAccount(tx.FromIdx)
  159. if err != nil {
  160. return err
  161. }
  162. accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
  163. // in case that the tx is a L1Tx>DepositAndTransfer
  164. if transfer {
  165. accReceiver, err := bb.localStateDB.GetAccount(tx.ToIdx)
  166. if err != nil {
  167. return err
  168. }
  169. // substract amount to the sender
  170. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Tx.Amount)
  171. // add amount to the receiver
  172. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Tx.Amount)
  173. // update receiver account in localStateDB
  174. err = bb.localStateDB.UpdateAccount(tx.ToIdx, accReceiver)
  175. if err != nil {
  176. return err
  177. }
  178. }
  179. // update sender account in localStateDB
  180. err = bb.localStateDB.UpdateAccount(tx.FromIdx, accSender)
  181. if err != nil {
  182. return err
  183. }
  184. return nil
  185. }
  186. // applyTransfer updates the balance & nonce in the account of the sender, and
  187. // the balance in the account of the receiver
  188. func (bb *BatchBuilder) applyTransfer(tx common.Tx) error {
  189. // get sender and receiver accounts from localStateDB
  190. accSender, err := bb.localStateDB.GetAccount(tx.FromIdx)
  191. if err != nil {
  192. return err
  193. }
  194. accReceiver, err := bb.localStateDB.GetAccount(tx.ToIdx)
  195. if err != nil {
  196. return err
  197. }
  198. // substract amount to the sender
  199. accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
  200. // add amount to the receiver
  201. accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
  202. // update receiver account in localStateDB
  203. err = bb.localStateDB.UpdateAccount(tx.ToIdx, accReceiver)
  204. if err != nil {
  205. return err
  206. }
  207. // update sender account in localStateDB
  208. err = bb.localStateDB.UpdateAccount(tx.FromIdx, accSender)
  209. if err != nil {
  210. return err
  211. }
  212. return nil
  213. }
  214. // getIdx returns the stored Idx from the localStateDB, which is the last Idx used for an Account in the localStateDB.
  215. func (bb *BatchBuilder) getIdx() (uint64, error) {
  216. idxBytes, err := bb.localStateDB.DB().Get(KEYIDX)
  217. if err == db.ErrNotFound {
  218. return 0, nil
  219. }
  220. if err != nil {
  221. return 0, err
  222. }
  223. idx := binary.LittleEndian.Uint64(idxBytes[:8])
  224. return idx, nil
  225. }
  226. // setIdx stores Idx in the localStateDB
  227. func (bb *BatchBuilder) setIdx(idx uint64) error {
  228. tx, err := bb.localStateDB.DB().NewTx()
  229. if err != nil {
  230. return err
  231. }
  232. var idxBytes [8]byte
  233. binary.LittleEndian.PutUint64(idxBytes[:], idx)
  234. tx.Put(KEYIDX, idxBytes[:])
  235. if err := tx.Commit(); err != nil {
  236. return err
  237. }
  238. return nil
  239. }