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