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