arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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-iden3-crypto/babyjub"
  7	"github.com/iden3/go-merkletree"
  8	"github.com/iden3/go-merkletree/db"
  9	"github.com/iden3/go-merkletree/db/memory"
 10)
 11
 12// ConfigCircuit contains the circuit configuration
 13type ConfigCircuit struct {
 14	TxsMax       uint64
 15	L1TxsMax     uint64
 16	SMTLevelsMax uint64
 17}
 18
 19// BatchBuilder implements the batch builder type, which contains the functionallities
 20type BatchBuilder struct {
 21	StateDB        db.Storage // where the MTs will be stored by the Synchronizer
 22	idx            uint64
 23	mt             *merkletree.MerkleTree
 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(stateDB db.Storage, configCircuits []ConfigCircuit, batchNum int, idx, nLevels uint64) (*BatchBuilder, error) {
 35	localMt, err := merkletree.NewMerkleTree(memory.NewMemoryStorage(), int(nLevels))
 36	if err != nil {
 37		return nil, err
 38	}
 39	bb := BatchBuilder{
 40		StateDB:        stateDB,
 41		idx:            idx,
 42		mt:             localMt,
 43		configCircuits: configCircuits,
 44	}
 45
 46	err = bb.Reset(batchNum, idx, 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, idx uint64, fromSynchronizer bool) error {
 55	// TODO
 56	return nil
 57}
 58
 59// BuildBatch takes the transactions and returns the common.ZKInputs of the next batch
 60func (bb *BatchBuilder) BuildBatch(configBatch ConfigBatch, l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.L2Tx, tokenIDs []common.TokenID) (*common.ZKInputs, error) {
 61	for _, tx := range l1usertxs {
 62		err := bb.processL1Tx(tx)
 63		if err != nil {
 64			return nil, err
 65		}
 66	}
 67	for _, tx := range l1coordinatortxs {
 68		err := bb.processL1Tx(tx)
 69		if err != nil {
 70			return nil, err
 71		}
 72	}
 73	for _, tx := range l2txs {
 74		switch tx.Type {
 75		case common.TxTypeTransfer:
 76			// go to the MT leaf of sender and receiver, and update
 77			// balance & nonce
 78			err := bb.applyTransfer(tx.Tx)
 79			if err != nil {
 80				return nil, err
 81			}
 82		case common.TxTypeExit:
 83			// execute exit flow
 84		default:
 85		}
 86	}
 87
 88	return nil, nil
 89}
 90
 91func (bb *BatchBuilder) processL1Tx(tx common.L1Tx) error {
 92	switch tx.Type {
 93	case common.TxTypeForceTransfer, common.TxTypeTransfer:
 94		// go to the MT leaf 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 leaf to the MT, update balance of the MT leaf
102		err := bb.applyCreateLeaf(tx)
103		if err != nil {
104			return err
105		}
106	case common.TxTypeDeposit:
107		// update balance of the MT leaf
108		err := bb.applyDeposit(tx, false)
109		if err != nil {
110			return err
111		}
112	case common.TxTypeDepositAndTransfer:
113		// update balance in MT leaf, 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 leaf to the merkletree, update balance in MT leaf,
121		// update balance & nonce of sender & receiver
122		err := bb.applyCreateLeaf(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
135	return nil
136}
137
138// applyCreateLeaf creates a new leaf in the leaf of the depositer, it stores
139// the deposit value
140func (bb *BatchBuilder) applyCreateLeaf(tx common.L1Tx) error {
141	leaf := common.Leaf{
142		TokenID: tx.TokenID,
143		Nonce:   0, // TODO check w spec: always that a new leaf is created nonce is at 0
144		Balance: tx.LoadAmount,
145		Sign:    babyjub.PointCoordSign(tx.FromBJJ.X),
146		Ay:      tx.FromBJJ.Y,
147		EthAddr: tx.FromEthAddr,
148	}
149
150	v, err := leaf.HashValue()
151	if err != nil {
152		return err
153	}
154	dbTx, err := bb.mt.DB().NewTx()
155	if err != nil {
156		return err
157	}
158
159	err = bb.CreateBalance(dbTx, common.Idx(bb.idx+1), leaf)
160	if err != nil {
161		return err
162	}
163	leafBytes, err := leaf.Bytes()
164	if err != nil {
165		return err
166	}
167	dbTx.Put(v.Bytes(), leafBytes[:])
168
169	// if everything is fine, do dbTx & increment idx
170	if err := dbTx.Commit(); err != nil {
171		return err
172	}
173	bb.idx = bb.idx + 1
174	return nil
175}
176
177// applyDeposit updates the balance in the leaf of the depositer, if andTransfer parameter is set to true, the method will also apply the Transfer of the L1Tx/DepositAndTransfer
178func (bb *BatchBuilder) applyDeposit(tx common.L1Tx, andTransfer bool) error {
179	dbTx, err := bb.mt.DB().NewTx()
180	if err != nil {
181		return err
182	}
183
184	// deposit
185	err = bb.UpdateBalance(dbTx, tx.FromIdx, tx.LoadAmount, false)
186	if err != nil {
187		return err
188	}
189
190	// in case that the tx is a L1Tx>DepositAndTransfer
191	if andTransfer {
192		// transact
193		err = bb.UpdateBalance(dbTx, tx.FromIdx, tx.Tx.Amount, true)
194		if err != nil {
195			return err
196		}
197		err = bb.UpdateBalance(dbTx, tx.ToIdx, tx.Tx.Amount, false)
198		if err != nil {
199			return err
200		}
201	}
202
203	if err := dbTx.Commit(); err != nil {
204		return err
205	}
206	return nil
207}
208
209// applyTransfer updates the balance & nonce in the leaf of the sender, and the
210// balance in the leaf of the receiver
211func (bb *BatchBuilder) applyTransfer(tx common.Tx) error {
212	dbTx, err := bb.mt.DB().NewTx()
213	if err != nil {
214		return err
215	}
216
217	// transact
218	err = bb.UpdateBalance(dbTx, tx.FromIdx, tx.Amount, true)
219	if err != nil {
220		return err
221	}
222	err = bb.UpdateBalance(dbTx, tx.ToIdx, tx.Amount, false)
223	if err != nil {
224		return err
225	}
226
227	if err := dbTx.Commit(); err != nil {
228		return err
229	}
230	return nil
231}