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-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}