arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/statedb/txprocessors.go
db/statedb/txprocessors.goRaw
  1package statedb
  2
  3import (
  4	"errors"
  5	"io/ioutil"
  6	"math/big"
  7	"os"
  8
  9	"github.com/hermeznetwork/hermez-node/common"
 10	"github.com/hermeznetwork/hermez-node/log"
 11	"github.com/iden3/go-iden3-crypto/babyjub"
 12	"github.com/iden3/go-merkletree"
 13	"github.com/iden3/go-merkletree/db"
 14	"github.com/iden3/go-merkletree/db/pebble"
 15)
 16
 17var (
 18	// keyidx is used as key in the db to store the current Idx
 19	keyidx = []byte("k:idx")
 20)
 21
 22func (s *StateDB) resetZKInputs() {
 23	s.zki = nil
 24	s.i = 0
 25}
 26
 27type processedExit struct {
 28	exit    bool
 29	newExit bool
 30	idx     common.Idx
 31	acc     common.Account
 32}
 33
 34// ProcessTxs process the given L1Txs & L2Txs applying the needed updates to
 35// the StateDB depending on the transaction Type.  If StateDB
 36// type==TypeBatchBuilder, returns the common.ZKInputs to generate the
 37// SnarkProof later used by the BatchBuilder.  If StateDB
 38// type==TypeSynchronizer, assumes that the call is done from the Synchronizer,
 39// returns common.ExitTreeLeaf that is later used by the Synchronizer to update
 40// the HistoryDB, and adds Nonce & TokenID to the L2Txs.
 41func (s *StateDB) ProcessTxs(l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.PoolL2Tx) (*common.ZKInputs, []common.ExitInfo, error) {
 42	var err error
 43	var exitTree *merkletree.MerkleTree
 44
 45	if s.zki != nil {
 46		return nil, nil, errors.New("Expected StateDB.zki==nil, something went wrong and it's not empty")
 47	}
 48	defer s.resetZKInputs()
 49
 50	nTx := len(l1usertxs) + len(l1coordinatortxs) + len(l2txs)
 51	if nTx == 0 {
 52		// TODO return ZKInputs of batch without txs
 53		return nil, nil, nil
 54	}
 55	exits := make([]processedExit, nTx)
 56
 57	if s.typ == TypeBatchBuilder {
 58		s.zki = common.NewZKInputs(nTx, 24, 32) // TODO this values will be parameters of the function, taken from config file/coordinator call
 59		s.zki.OldLastIdx = (s.idx - 1).BigInt()
 60		s.zki.OldStateRoot = s.mt.Root().BigInt()
 61	}
 62
 63	// TBD if ExitTree is only in memory or stored in disk, for the moment
 64	// only needed in memory
 65	if s.typ == TypeSynchronizer || s.typ == TypeBatchBuilder {
 66		tmpDir, err := ioutil.TempDir("", "hermez-statedb-exittree")
 67		if err != nil {
 68			return nil, nil, err
 69		}
 70		defer func() {
 71			if err := os.RemoveAll(tmpDir); err != nil {
 72				log.Errorw("Deleting statedb temp exit tree", "err", err)
 73			}
 74		}()
 75		sto, err := pebble.NewPebbleStorage(tmpDir, false)
 76		if err != nil {
 77			return nil, nil, err
 78		}
 79		exitTree, err = merkletree.NewMerkleTree(sto, s.mt.MaxLevels())
 80		if err != nil {
 81			return nil, nil, err
 82		}
 83	}
 84
 85	// assumption: l1usertx are sorted by L1Tx.Position
 86	for i := 0; i < len(l1usertxs); i++ {
 87		exitIdx, exitAccount, newExit, err := s.processL1Tx(exitTree, &l1usertxs[i])
 88		if err != nil {
 89			return nil, nil, err
 90		}
 91		if s.typ == TypeSynchronizer || s.typ == TypeBatchBuilder {
 92			if exitIdx != nil && exitTree != nil {
 93				exits[s.i] = processedExit{
 94					exit:    true,
 95					newExit: newExit,
 96					idx:     *exitIdx,
 97					acc:     *exitAccount,
 98				}
 99			}
100			s.i++
101		}
102	}
103	for i := 0; i < len(l1coordinatortxs); i++ {
104		exitIdx, exitAccount, newExit, err := s.processL1Tx(exitTree, &l1coordinatortxs[i])
105		if err != nil {
106			return nil, nil, err
107		}
108		if exitIdx != nil {
109			log.Error("Unexpected Exit in L1CoordinatorTx")
110		}
111		if s.typ == TypeSynchronizer || s.typ == TypeBatchBuilder {
112			if exitIdx != nil && exitTree != nil {
113				exits[s.i] = processedExit{
114					exit:    true,
115					newExit: newExit,
116					idx:     *exitIdx,
117					acc:     *exitAccount,
118				}
119			}
120			s.i++
121		}
122	}
123	for i := 0; i < len(l2txs); i++ {
124		exitIdx, exitAccount, newExit, err := s.processL2Tx(exitTree, &l2txs[i])
125		if err != nil {
126			return nil, nil, err
127		}
128		if s.typ == TypeSynchronizer || s.typ == TypeBatchBuilder {
129			if exitIdx != nil && exitTree != nil {
130				exits[s.i] = processedExit{
131					exit:    true,
132					newExit: newExit,
133					idx:     *exitIdx,
134					acc:     *exitAccount,
135				}
136			}
137			s.i++
138		}
139	}
140
141	if s.typ == TypeTxSelector {
142		return nil, nil, nil
143	}
144
145	// once all txs processed (exitTree root frozen), for each Exit,
146	// generate common.ExitInfo data
147	var exitInfos []common.ExitInfo
148	for i := 0; i < nTx; i++ {
149		if !exits[i].exit {
150			continue
151		}
152		exitIdx := exits[i].idx
153		exitAccount := exits[i].acc
154
155		// 0. generate MerkleProof
156		p, err := exitTree.GenerateCircomVerifierProof(exitIdx.BigInt(), nil)
157		if err != nil {
158			return nil, nil, err
159		}
160		// 1. generate common.ExitInfo
161		ei := common.ExitInfo{
162			AccountIdx:  exitIdx,
163			MerkleProof: p,
164			Balance:     exitAccount.Balance,
165		}
166		exitInfos = append(exitInfos, ei)
167
168		if s.zki != nil {
169			s.zki.TokenID2[i] = exitAccount.TokenID.BigInt()
170			s.zki.Nonce2[i] = exitAccount.Nonce.BigInt()
171			if babyjub.PointCoordSign(exitAccount.PublicKey.X) {
172				s.zki.Sign2[i] = big.NewInt(1)
173			}
174			s.zki.Ay2[i] = exitAccount.PublicKey.Y
175			s.zki.Balance2[i] = exitAccount.Balance
176			s.zki.EthAddr2[i] = common.EthAddrToBigInt(exitAccount.EthAddr)
177			s.zki.Siblings2[i] = p.Siblings
178			if exits[i].newExit {
179				s.zki.NewExit[i] = big.NewInt(1)
180			}
181			if p.IsOld0 {
182				s.zki.IsOld0_2[i] = big.NewInt(1)
183			}
184			s.zki.OldKey2[i] = p.OldKey.BigInt()
185			s.zki.OldValue2[i] = p.OldValue.BigInt()
186		}
187	}
188	if s.typ == TypeSynchronizer {
189		return nil, exitInfos, nil
190	}
191
192	// compute last ZKInputs parameters
193	s.zki.GlobalChainID = big.NewInt(0) // TODO, 0: ethereum, this will be get from config file
194	// zki.FeeIdxs = ? // TODO, this will be get from the config file
195	tokenIDs, err := s.getTokenIDsBigInt(l1usertxs, l1coordinatortxs, l2txs)
196	if err != nil {
197		return nil, nil, err
198	}
199	s.zki.FeePlanTokens = tokenIDs
200
201	// s.zki.ISInitStateRootFee = s.mt.Root().BigInt()
202
203	// TODO once the Node Config sets the Accounts where to send the Fees
204	// compute fees & update ZKInputs
205
206	// return exitInfos, so Synchronizer will be able to store it into
207	// HistoryDB for the concrete BatchNum
208	return s.zki, exitInfos, nil
209}
210
211// getTokenIDsBigInt returns the list of TokenIDs in *big.Int format
212func (s *StateDB) getTokenIDsBigInt(l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.PoolL2Tx) ([]*big.Int, error) {
213	tokenIDs := make(map[common.TokenID]bool)
214	for i := 0; i < len(l1usertxs); i++ {
215		tokenIDs[l1usertxs[i].TokenID] = true
216	}
217	for i := 0; i < len(l1coordinatortxs); i++ {
218		tokenIDs[l1coordinatortxs[i].TokenID] = true
219	}
220	for i := 0; i < len(l2txs); i++ {
221		// as L2Tx does not have parameter TokenID, get it from the
222		// AccountsDB (in the StateDB)
223		acc, err := s.GetAccount(l2txs[i].ToIdx)
224		if err != nil {
225			return nil, err
226		}
227		tokenIDs[acc.TokenID] = true
228	}
229	var tBI []*big.Int
230	for t := range tokenIDs {
231		tBI = append(tBI, t.BigInt())
232	}
233	return tBI, nil
234}
235
236// processL1Tx process the given L1Tx applying the needed updates to the
237// StateDB depending on the transaction Type. It returns the 3 parameters
238// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
239// the Exit created a new Leaf in the ExitTree.
240func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx) (*common.Idx, *common.Account, bool, error) {
241	// ZKInputs
242	if s.zki != nil {
243		// Txs
244		// s.zki.TxCompressedData[s.i] = tx.TxCompressedData() // uncomment once L1Tx.TxCompressedData is ready
245		s.zki.FromIdx[s.i] = tx.FromIdx.BigInt()
246		s.zki.ToIdx[s.i] = tx.ToIdx.BigInt()
247		s.zki.OnChain[s.i] = big.NewInt(1)
248
249		// L1Txs
250		s.zki.LoadAmountF[s.i] = tx.LoadAmount
251		s.zki.FromEthAddr[s.i] = common.EthAddrToBigInt(tx.FromEthAddr)
252		if tx.FromBJJ != nil {
253			s.zki.FromBJJCompressed[s.i] = BJJCompressedTo256BigInts(tx.FromBJJ.Compress())
254		}
255
256		// Intermediate States
257		s.zki.ISOnChain[s.i] = big.NewInt(1)
258	}
259
260	switch tx.Type {
261	case common.TxTypeForceTransfer, common.TxTypeTransfer:
262		// go to the MT account of sender and receiver, and update balance
263		// & nonce
264		err := s.applyTransfer(tx.Tx(), 0) // 0 for the parameter toIdx, as at L1Tx ToIdx can only be 0 in the Deposit type case.
265		if err != nil {
266			log.Error(err)
267			return nil, nil, false, err
268		}
269	case common.TxTypeCreateAccountDeposit:
270		// add new account to the MT, update balance of the MT account
271		err := s.applyCreateAccount(tx)
272		if err != nil {
273			log.Error(err)
274			return nil, nil, false, err
275		}
276		// TODO applyCreateAccount will return the created account,
277		// which in the case type==TypeSynchronizer will be added to an
278		// array of created accounts that will be returned
279
280		if s.zki != nil {
281			s.zki.AuxFromIdx[s.i] = s.idx.BigInt() // last s.idx is the one used for creating the new account
282			s.zki.NewAccount[s.i] = big.NewInt(1)
283		}
284	case common.TxTypeDeposit:
285		// update balance of the MT account
286		err := s.applyDeposit(tx, false)
287		if err != nil {
288			log.Error(err)
289			return nil, nil, false, err
290		}
291	case common.TxTypeDepositTransfer:
292		// update balance in MT account, update balance & nonce of sender
293		// & receiver
294		err := s.applyDeposit(tx, true)
295		if err != nil {
296			log.Error(err)
297			return nil, nil, false, err
298		}
299	case common.TxTypeCreateAccountDepositTransfer:
300		// add new account to the merkletree, update balance in MT account,
301		// update balance & nonce of sender & receiver
302		err := s.applyCreateAccountDepositTransfer(tx)
303		if err != nil {
304			log.Error(err)
305			return nil, nil, false, err
306		}
307
308		if s.zki != nil {
309			s.zki.AuxFromIdx[s.i] = s.idx.BigInt() // last s.idx is the one used for creating the new account
310			s.zki.NewAccount[s.i] = big.NewInt(1)
311		}
312	case common.TxTypeExit:
313		// execute exit flow
314		exitAccount, newExit, err := s.applyExit(exitTree, tx.Tx())
315		if err != nil {
316			log.Error(err)
317			return nil, nil, false, err
318		}
319		return &tx.FromIdx, exitAccount, newExit, nil
320	default:
321	}
322
323	return nil, nil, false, nil
324}
325
326// processL2Tx process the given L2Tx applying the needed updates to the
327// StateDB depending on the transaction Type. It returns the 3 parameters
328// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
329// the Exit created a new Leaf in the ExitTree.
330func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2Tx) (*common.Idx, *common.Account, bool, error) {
331	var err error
332	// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
333	if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
334		tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ)
335		if err != nil {
336			log.Error(err)
337			return nil, nil, false, err
338		}
339	}
340
341	// ZKInputs
342	if s.zki != nil {
343		// Txs
344		// s.zki.TxCompressedData[s.i] = tx.TxCompressedData() // uncomment once L1Tx.TxCompressedData is ready
345		// s.zki.TxCompressedDataV2[s.i] = tx.TxCompressedDataV2() // uncomment once L2Tx.TxCompressedDataV2 is ready
346		s.zki.FromIdx[s.i] = tx.FromIdx.BigInt()
347		s.zki.ToIdx[s.i] = tx.ToIdx.BigInt()
348
349		// fill AuxToIdx if needed
350		if tx.ToIdx == 0 {
351			// use toIdx that can have been filled by tx.ToIdx or
352			// if tx.Idx==0 (this case), toIdx is filled by the Idx
353			// from db by ToEthAddr&ToBJJ
354			s.zki.AuxToIdx[s.i] = tx.AuxToIdx.BigInt()
355		}
356
357		if tx.ToBJJ != nil {
358			s.zki.ToBJJAy[s.i] = tx.ToBJJ.Y
359		}
360		s.zki.ToEthAddr[s.i] = common.EthAddrToBigInt(tx.ToEthAddr)
361
362		s.zki.OnChain[s.i] = big.NewInt(0)
363		s.zki.NewAccount[s.i] = big.NewInt(0)
364
365		// L2Txs
366		// s.zki.RqOffset[s.i] =  // TODO Rq once TxSelector is ready
367		// s.zki.RqTxCompressedDataV2[s.i] = // TODO
368		// s.zki.RqToEthAddr[s.i] = common.EthAddrToBigInt(tx.RqToEthAddr) // TODO
369		// s.zki.RqToBJJAy[s.i] = tx.ToBJJ.Y // TODO
370		s.zki.S[s.i] = tx.Signature.S
371		s.zki.R8x[s.i] = tx.Signature.R8.X
372		s.zki.R8y[s.i] = tx.Signature.R8.Y
373	}
374
375	// if StateDB type==TypeSynchronizer, will need to add Nonce
376	if s.typ == TypeSynchronizer {
377		// as type==TypeSynchronizer, always tx.ToIdx!=0
378		acc, err := s.GetAccount(tx.FromIdx)
379		if err != nil {
380			log.Error(err)
381			return nil, nil, false, err
382		}
383		tx.Nonce = acc.Nonce
384		tx.TokenID = acc.TokenID
385	}
386
387	switch tx.Type {
388	case common.TxTypeTransfer:
389		// go to the MT account of sender and receiver, and update
390		// balance & nonce
391		err = s.applyTransfer(tx.Tx(), tx.AuxToIdx)
392		if err != nil {
393			log.Error(err)
394			return nil, nil, false, err
395		}
396	case common.TxTypeExit:
397		// execute exit flow
398		exitAccount, newExit, err := s.applyExit(exitTree, tx.Tx())
399		if err != nil {
400			log.Error(err)
401			return nil, nil, false, err
402		}
403		return &tx.FromIdx, exitAccount, newExit, nil
404	default:
405	}
406	return nil, nil, false, nil
407}
408
409// applyCreateAccount creates a new account in the account of the depositer, it
410// stores the deposit value
411func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
412	account := &common.Account{
413		TokenID:   tx.TokenID,
414		Nonce:     0,
415		Balance:   tx.LoadAmount,
416		PublicKey: tx.FromBJJ,
417		EthAddr:   tx.FromEthAddr,
418	}
419
420	p, err := s.CreateAccount(common.Idx(s.idx+1), account)
421	if err != nil {
422		return err
423	}
424	if s.zki != nil {
425		s.zki.TokenID1[s.i] = tx.TokenID.BigInt()
426		s.zki.Nonce1[s.i] = big.NewInt(0)
427		if babyjub.PointCoordSign(tx.FromBJJ.X) {
428			s.zki.Sign1[s.i] = big.NewInt(1)
429		}
430		s.zki.Ay1[s.i] = tx.FromBJJ.Y
431		s.zki.Balance1[s.i] = tx.LoadAmount
432		s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(tx.FromEthAddr)
433		s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
434		if p.IsOld0 {
435			s.zki.IsOld0_1[s.i] = big.NewInt(1)
436		}
437		s.zki.OldKey1[s.i] = p.OldKey.BigInt()
438		s.zki.OldValue1[s.i] = p.OldValue.BigInt()
439	}
440
441	s.idx = s.idx + 1
442	return s.setIdx(s.idx)
443}
444
445// applyDeposit updates the balance in the account of the depositer, if
446// andTransfer parameter is set to true, the method will also apply the
447// Transfer of the L1Tx/DepositTransfer
448func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
449	// deposit the tx.LoadAmount into the sender account
450	accSender, err := s.GetAccount(tx.FromIdx)
451	if err != nil {
452		return err
453	}
454	accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
455
456	// in case that the tx is a L1Tx>DepositTransfer
457	var accReceiver *common.Account
458	if transfer {
459		accReceiver, err = s.GetAccount(tx.ToIdx)
460		if err != nil {
461			return err
462		}
463		// subtract amount to the sender
464		accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
465		// add amount to the receiver
466		accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
467	}
468	// update sender account in localStateDB
469	p, err := s.UpdateAccount(tx.FromIdx, accSender)
470	if err != nil {
471		return err
472	}
473	if s.zki != nil {
474		s.zki.TokenID1[s.i] = accSender.TokenID.BigInt()
475		s.zki.Nonce1[s.i] = accSender.Nonce.BigInt()
476		if babyjub.PointCoordSign(accSender.PublicKey.X) {
477			s.zki.Sign1[s.i] = big.NewInt(1)
478		}
479		s.zki.Ay1[s.i] = accSender.PublicKey.Y
480		s.zki.Balance1[s.i] = accSender.Balance
481		s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(accSender.EthAddr)
482		s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
483		// IsOld0_1, OldKey1, OldValue1 not needed as this is not an insert
484	}
485
486	// this is done after updating Sender Account (depositer)
487	if transfer {
488		// update receiver account in localStateDB
489		p, err := s.UpdateAccount(tx.ToIdx, accReceiver)
490		if err != nil {
491			return err
492		}
493		if s.zki != nil {
494			s.zki.TokenID2[s.i] = accReceiver.TokenID.BigInt()
495			s.zki.Nonce2[s.i] = accReceiver.Nonce.BigInt()
496			if babyjub.PointCoordSign(accReceiver.PublicKey.X) {
497				s.zki.Sign2[s.i] = big.NewInt(1)
498			}
499			s.zki.Ay2[s.i] = accReceiver.PublicKey.Y
500			s.zki.Balance2[s.i] = accReceiver.Balance
501			s.zki.EthAddr2[s.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
502			s.zki.Siblings2[s.i] = siblingsToZKInputFormat(p.Siblings)
503			// IsOld0_2, OldKey2, OldValue2 not needed as this is not an insert
504		}
505	}
506
507	return nil
508}
509
510// applyTransfer updates the balance & nonce in the account of the sender, and
511// the balance in the account of the receiver.
512// Parameter 'toIdx' should be at 0 if the tx already has tx.ToIdx!=0, if
513// tx.ToIdx==0, then toIdx!=0, and will be used the toIdx parameter as Idx of
514// the receiver. This parameter is used when the tx.ToIdx is not specified and
515// the real ToIdx is found trhrough the ToEthAddr or ToBJJ.
516func (s *StateDB) applyTransfer(tx common.Tx, auxToIdx common.Idx) error {
517	if auxToIdx == common.Idx(0) {
518		auxToIdx = tx.ToIdx
519	}
520	// get sender and receiver accounts from localStateDB
521	accSender, err := s.GetAccount(tx.FromIdx)
522	if err != nil {
523		log.Error(err)
524		return err
525	}
526	accReceiver, err := s.GetAccount(auxToIdx)
527	if err != nil {
528		log.Error(err)
529		return err
530	}
531
532	// increment nonce
533	accSender.Nonce++
534
535	// subtract amount to the sender
536	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
537	// add amount to the receiver
538	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
539
540	// update sender account in localStateDB
541	pSender, err := s.UpdateAccount(tx.FromIdx, accSender)
542	if err != nil {
543		log.Error(err)
544		return err
545	}
546	if s.zki != nil {
547		s.zki.TokenID1[s.i] = accSender.TokenID.BigInt()
548		s.zki.Nonce1[s.i] = accSender.Nonce.BigInt()
549		if babyjub.PointCoordSign(accSender.PublicKey.X) {
550			s.zki.Sign1[s.i] = big.NewInt(1)
551		}
552		s.zki.Ay1[s.i] = accSender.PublicKey.Y
553		s.zki.Balance1[s.i] = accSender.Balance
554		s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(accSender.EthAddr)
555		s.zki.Siblings1[s.i] = siblingsToZKInputFormat(pSender.Siblings)
556	}
557
558	// update receiver account in localStateDB
559	pReceiver, err := s.UpdateAccount(auxToIdx, accReceiver)
560	if err != nil {
561		return err
562	}
563	if s.zki != nil {
564		s.zki.TokenID2[s.i] = accReceiver.TokenID.BigInt()
565		s.zki.Nonce2[s.i] = accReceiver.Nonce.BigInt()
566		if babyjub.PointCoordSign(accReceiver.PublicKey.X) {
567			s.zki.Sign2[s.i] = big.NewInt(1)
568		}
569		s.zki.Ay2[s.i] = accReceiver.PublicKey.Y
570		s.zki.Balance2[s.i] = accReceiver.Balance
571		s.zki.EthAddr2[s.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
572		s.zki.Siblings2[s.i] = siblingsToZKInputFormat(pReceiver.Siblings)
573	}
574
575	return nil
576}
577
578// applyCreateAccountDepositTransfer, in a single tx, creates a new account,
579// makes a deposit, and performs a transfer to another account
580func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
581	accSender := &common.Account{
582		TokenID:   tx.TokenID,
583		Nonce:     0,
584		Balance:   tx.LoadAmount,
585		PublicKey: tx.FromBJJ,
586		EthAddr:   tx.FromEthAddr,
587	}
588	accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
589	accReceiver, err := s.GetAccount(tx.ToIdx)
590	if err != nil {
591		return err
592	}
593	// subtract amount to the sender
594	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
595	// add amount to the receiver
596	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
597
598	// create Account of the Sender
599	p, err := s.CreateAccount(common.Idx(s.idx+1), accSender)
600	if err != nil {
601		return err
602	}
603	if s.zki != nil {
604		s.zki.TokenID1[s.i] = tx.TokenID.BigInt()
605		s.zki.Nonce1[s.i] = big.NewInt(0)
606		if babyjub.PointCoordSign(tx.FromBJJ.X) {
607			s.zki.Sign1[s.i] = big.NewInt(1)
608		}
609		s.zki.Ay1[s.i] = tx.FromBJJ.Y
610		s.zki.Balance1[s.i] = tx.LoadAmount
611		s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(tx.FromEthAddr)
612		s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
613		if p.IsOld0 {
614			s.zki.IsOld0_1[s.i] = big.NewInt(1)
615		}
616		s.zki.OldKey1[s.i] = p.OldKey.BigInt()
617		s.zki.OldValue1[s.i] = p.OldValue.BigInt()
618	}
619
620	// update receiver account in localStateDB
621	p, err = s.UpdateAccount(tx.ToIdx, accReceiver)
622	if err != nil {
623		return err
624	}
625	if s.zki != nil {
626		s.zki.TokenID2[s.i] = accReceiver.TokenID.BigInt()
627		s.zki.Nonce2[s.i] = accReceiver.Nonce.BigInt()
628		if babyjub.PointCoordSign(accReceiver.PublicKey.X) {
629			s.zki.Sign2[s.i] = big.NewInt(1)
630		}
631		s.zki.Ay2[s.i] = accReceiver.PublicKey.Y
632		s.zki.Balance2[s.i] = accReceiver.Balance
633		s.zki.EthAddr2[s.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
634		s.zki.Siblings2[s.i] = siblingsToZKInputFormat(p.Siblings)
635	}
636
637	s.idx = s.idx + 1
638	return s.setIdx(s.idx)
639}
640
641// It returns the ExitAccount and a boolean determining if the Exit created a
642// new Leaf in the ExitTree.
643func (s *StateDB) applyExit(exitTree *merkletree.MerkleTree, tx common.Tx) (*common.Account, bool, error) {
644	// 0. subtract tx.Amount from current Account in StateMT
645	// add the tx.Amount into the Account (tx.FromIdx) in the ExitMT
646	acc, err := s.GetAccount(tx.FromIdx)
647	if err != nil {
648		return nil, false, err
649	}
650	acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount)
651	p, err := s.UpdateAccount(tx.FromIdx, acc)
652	if err != nil {
653		return nil, false, err
654	}
655	if s.zki != nil {
656		s.zki.TokenID1[s.i] = acc.TokenID.BigInt()
657		s.zki.Nonce1[s.i] = acc.Nonce.BigInt()
658		if babyjub.PointCoordSign(acc.PublicKey.X) {
659			s.zki.Sign1[s.i] = big.NewInt(1)
660		}
661		s.zki.Ay1[s.i] = acc.PublicKey.Y
662		s.zki.Balance1[s.i] = acc.Balance
663		s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(acc.EthAddr)
664		s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
665	}
666
667	if exitTree == nil {
668		return nil, false, nil
669	}
670	exitAccount, err := getAccountInTreeDB(exitTree.DB(), tx.FromIdx)
671	if err == db.ErrNotFound {
672		// 1a. if idx does not exist in exitTree:
673		// add new leaf 'ExitTreeLeaf', where ExitTreeLeaf.Balance = exitAmount (exitAmount=tx.Amount)
674		exitAccount := &common.Account{
675			TokenID:   acc.TokenID,
676			Nonce:     common.Nonce(1),
677			Balance:   tx.Amount,
678			PublicKey: acc.PublicKey,
679			EthAddr:   acc.EthAddr,
680		}
681		_, err = createAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
682		return exitAccount, true, err
683	} else if err != nil {
684		return exitAccount, false, err
685	}
686
687	// 1b. if idx already exist in exitTree:
688	// update account, where account.Balance += exitAmount
689	exitAccount.Balance = new(big.Int).Add(exitAccount.Balance, tx.Amount)
690	_, err = updateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
691	return exitAccount, false, err
692}
693
694// getIdx returns the stored Idx from the localStateDB, which is the last Idx
695// used for an Account in the localStateDB.
696func (s *StateDB) getIdx() (common.Idx, error) {
697	idxBytes, err := s.DB().Get(keyidx)
698	if err == db.ErrNotFound {
699		return 0, nil
700	}
701	if err != nil {
702		return 0, err
703	}
704	return common.IdxFromBytes(idxBytes[:4])
705}
706
707// setIdx stores Idx in the localStateDB
708func (s *StateDB) setIdx(idx common.Idx) error {
709	tx, err := s.DB().NewTx()
710	if err != nil {
711		return err
712	}
713	idxBytes, err := idx.Bytes()
714	if err != nil {
715		return err
716	}
717	err = tx.Put(keyidx, idxBytes[:])
718	if err != nil {
719		return err
720	}
721	if err := tx.Commit(); err != nil {
722		return err
723	}
724	return nil
725}