arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/txprocessor/txprocessor.go
txprocessor/txprocessor.goRaw
   1package txprocessor
   2
   3import (
   4	"bytes"
   5	"errors"
   6	"fmt"
   7	"io/ioutil"
   8	"math/big"
   9	"os"
  10
  11	"github.com/hermeznetwork/hermez-node/common"
  12	"github.com/hermeznetwork/hermez-node/db/statedb"
  13	"github.com/hermeznetwork/hermez-node/log"
  14	"github.com/hermeznetwork/tracerr"
  15	"github.com/iden3/go-iden3-crypto/babyjub"
  16	"github.com/iden3/go-merkletree"
  17	"github.com/iden3/go-merkletree/db"
  18	"github.com/iden3/go-merkletree/db/pebble"
  19)
  20
  21// TxProcessor represents the TxProcessor object
  22type TxProcessor struct {
  23	s   *statedb.StateDB
  24	zki *common.ZKInputs
  25	// i is the current transaction index in the ZKInputs generation (zki)
  26	i int
  27	// AccumulatedFees contains the accumulated fees for each token (Coord
  28	// Idx) in the processed batch
  29	AccumulatedFees map[common.Idx]*big.Int
  30	config          Config
  31}
  32
  33// Config contains the TxProcessor configuration parameters
  34type Config struct {
  35	NLevels  uint32
  36	MaxFeeTx uint32
  37	MaxTx    uint32
  38	MaxL1Tx  uint32
  39	ChainID  uint16
  40}
  41
  42type processedExit struct {
  43	exit    bool
  44	newExit bool
  45	idx     common.Idx
  46	acc     common.Account
  47}
  48
  49// ProcessTxOutput contains the output of the ProcessTxs method
  50type ProcessTxOutput struct {
  51	ZKInputs           *common.ZKInputs
  52	ExitInfos          []common.ExitInfo
  53	CreatedAccounts    []common.Account
  54	CoordinatorIdxsMap map[common.TokenID]common.Idx
  55	CollectedFees      map[common.TokenID]*big.Int
  56}
  57
  58func newErrorNotEnoughBalance(tx common.Tx) error {
  59	var msg error
  60	if tx.IsL1 {
  61		msg = fmt.Errorf("Invalid transaction, not enough balance on sender account. TxID: %s, TxType: %s, FromIdx: %d, ToIdx: %d, Amount: %d",
  62			tx.TxID, tx.Type, tx.FromIdx, tx.ToIdx, tx.Amount)
  63	} else {
  64		msg = fmt.Errorf("Invalid transaction, not enough balance on sender account. TxID: %s, TxType: %s, FromIdx: %d, ToIdx: %d, Amount: %d, Fee: %d",
  65			tx.TxID, tx.Type, tx.FromIdx, tx.ToIdx, tx.Amount, tx.Fee)
  66	}
  67	return tracerr.Wrap(msg)
  68}
  69
  70// NewTxProcessor returns a new TxProcessor with the given *StateDB & Config
  71func NewTxProcessor(sdb *statedb.StateDB, config Config) *TxProcessor {
  72	return &TxProcessor{
  73		s:      sdb,
  74		zki:    nil,
  75		i:      0,
  76		config: config,
  77	}
  78}
  79
  80// StateDB returns a pointer to the StateDB of the TxProcessor
  81func (tp *TxProcessor) StateDB() *statedb.StateDB {
  82	return tp.s
  83}
  84
  85func (tp *TxProcessor) resetZKInputs() {
  86	tp.zki = nil
  87	tp.i = 0 // initialize current transaction index in the ZKInputs generation
  88}
  89
  90// ProcessTxs process the given L1Txs & L2Txs applying the needed updates to
  91// the StateDB depending on the transaction Type.  If StateDB
  92// type==TypeBatchBuilder, returns the common.ZKInputs to generate the
  93// SnarkProof later used by the BatchBuilder.  If StateDB
  94// type==TypeSynchronizer, assumes that the call is done from the Synchronizer,
  95// returns common.ExitTreeLeaf that is later used by the Synchronizer to update
  96// the HistoryDB, and adds Nonce & TokenID to the L2Txs.
  97// And if TypeSynchronizer returns an array of common.Account with all the
  98// created accounts.
  99func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinatortxs []common.L1Tx,
 100	l2txs []common.PoolL2Tx) (ptOut *ProcessTxOutput, err error) {
 101	defer func() {
 102		if err == nil {
 103			err = tp.s.MakeCheckpoint()
 104		}
 105	}()
 106
 107	var exitTree *merkletree.MerkleTree
 108	var createdAccounts []common.Account
 109
 110	if tp.zki != nil {
 111		return nil, tracerr.Wrap(errors.New("Expected StateDB.zki==nil, something went wrong and it's not empty"))
 112	}
 113	defer tp.resetZKInputs()
 114
 115	if len(coordIdxs) >= int(tp.config.MaxFeeTx) {
 116		return nil, tracerr.Wrap(fmt.Errorf("CoordIdxs (%d) length must be smaller than MaxFeeTx (%d)", len(coordIdxs), tp.config.MaxFeeTx))
 117	}
 118
 119	nTx := len(l1usertxs) + len(l1coordinatortxs) + len(l2txs)
 120
 121	if nTx > int(tp.config.MaxTx) {
 122		return nil, tracerr.Wrap(fmt.Errorf("L1UserTx + L1CoordinatorTx + L2Tx (%d) can not be bigger than MaxTx (%d)", nTx, tp.config.MaxTx))
 123	}
 124	if len(l1usertxs)+len(l1coordinatortxs) > int(tp.config.MaxL1Tx) {
 125		return nil, tracerr.Wrap(fmt.Errorf("L1UserTx + L1CoordinatorTx (%d) can not be bigger than MaxL1Tx (%d)", len(l1usertxs)+len(l1coordinatortxs), tp.config.MaxTx))
 126	}
 127
 128	exits := make([]processedExit, nTx)
 129
 130	if tp.s.Type() == statedb.TypeBatchBuilder {
 131		tp.zki = common.NewZKInputs(tp.config.ChainID, tp.config.MaxTx, tp.config.MaxL1Tx,
 132			tp.config.MaxFeeTx, tp.config.NLevels, (tp.s.CurrentBatch() + 1).BigInt())
 133		tp.zki.OldLastIdx = tp.s.CurrentIdx().BigInt()
 134		tp.zki.OldStateRoot = tp.s.MT.Root().BigInt()
 135		tp.zki.Metadata.NewLastIdxRaw = tp.s.CurrentIdx()
 136	}
 137
 138	// TBD if ExitTree is only in memory or stored in disk, for the moment
 139	// is only needed in memory
 140	if tp.s.Type() == statedb.TypeSynchronizer || tp.s.Type() == statedb.TypeBatchBuilder {
 141		tmpDir, err := ioutil.TempDir("", "hermez-statedb-exittree")
 142		if err != nil {
 143			return nil, tracerr.Wrap(err)
 144		}
 145		defer func() {
 146			if err := os.RemoveAll(tmpDir); err != nil {
 147				log.Errorw("Deleting statedb temp exit tree", "err", err)
 148			}
 149		}()
 150		sto, err := pebble.NewPebbleStorage(tmpDir, false)
 151		if err != nil {
 152			return nil, tracerr.Wrap(err)
 153		}
 154		defer sto.Close()
 155		exitTree, err = merkletree.NewMerkleTree(sto, tp.s.MT.MaxLevels())
 156		if err != nil {
 157			return nil, tracerr.Wrap(err)
 158		}
 159	}
 160
 161	// Process L1UserTxs
 162	for i := 0; i < len(l1usertxs); i++ {
 163		// assumption: l1usertx are sorted by L1Tx.Position
 164		exitIdx, exitAccount, newExit, createdAccount, err := tp.ProcessL1Tx(exitTree,
 165			&l1usertxs[i])
 166		if err != nil {
 167			return nil, tracerr.Wrap(err)
 168		}
 169		if tp.s.Type() == statedb.TypeSynchronizer {
 170			if createdAccount != nil {
 171				createdAccounts = append(createdAccounts, *createdAccount)
 172				l1usertxs[i].EffectiveFromIdx = createdAccount.Idx
 173			} else {
 174				l1usertxs[i].EffectiveFromIdx = l1usertxs[i].FromIdx
 175			}
 176		}
 177		if tp.zki != nil {
 178			l1TxData, err := l1usertxs[i].BytesGeneric()
 179			if err != nil {
 180				return nil, tracerr.Wrap(err)
 181			}
 182			tp.zki.Metadata.L1TxsData = append(tp.zki.Metadata.L1TxsData, l1TxData)
 183
 184			l1TxDataAvailability, err :=
 185				l1usertxs[i].BytesDataAvailability(tp.zki.Metadata.NLevels)
 186			if err != nil {
 187				return nil, tracerr.Wrap(err)
 188			}
 189			tp.zki.Metadata.L1TxsDataAvailability =
 190				append(tp.zki.Metadata.L1TxsDataAvailability, l1TxDataAvailability)
 191
 192			tp.zki.ISOutIdx[tp.i] = tp.s.CurrentIdx().BigInt()
 193			tp.zki.ISStateRoot[tp.i] = tp.s.MT.Root().BigInt()
 194			if exitIdx == nil {
 195				tp.zki.ISExitRoot[tp.i] = exitTree.Root().BigInt()
 196			}
 197		}
 198		if tp.s.Type() == statedb.TypeSynchronizer || tp.s.Type() == statedb.TypeBatchBuilder {
 199			if exitIdx != nil && exitTree != nil {
 200				exits[tp.i] = processedExit{
 201					exit:    true,
 202					newExit: newExit,
 203					idx:     *exitIdx,
 204					acc:     *exitAccount,
 205				}
 206			}
 207			tp.i++
 208		}
 209	}
 210
 211	// Process L1CoordinatorTxs
 212	for i := 0; i < len(l1coordinatortxs); i++ {
 213		exitIdx, _, _, createdAccount, err := tp.ProcessL1Tx(exitTree, &l1coordinatortxs[i])
 214		if err != nil {
 215			return nil, tracerr.Wrap(err)
 216		}
 217		if exitIdx != nil {
 218			log.Error("Unexpected Exit in L1CoordinatorTx")
 219		}
 220		if tp.s.Type() == statedb.TypeSynchronizer {
 221			if createdAccount != nil {
 222				createdAccounts = append(createdAccounts, *createdAccount)
 223				l1coordinatortxs[i].EffectiveFromIdx = createdAccount.Idx
 224			} else {
 225				l1coordinatortxs[i].EffectiveFromIdx = l1coordinatortxs[i].FromIdx
 226			}
 227		}
 228		if tp.zki != nil {
 229			l1TxData, err := l1coordinatortxs[i].BytesGeneric()
 230			if err != nil {
 231				return nil, tracerr.Wrap(err)
 232			}
 233			tp.zki.Metadata.L1TxsData = append(tp.zki.Metadata.L1TxsData, l1TxData)
 234			l1TxDataAvailability, err :=
 235				l1coordinatortxs[i].BytesDataAvailability(tp.zki.Metadata.NLevels)
 236			if err != nil {
 237				return nil, tracerr.Wrap(err)
 238			}
 239			tp.zki.Metadata.L1TxsDataAvailability =
 240				append(tp.zki.Metadata.L1TxsDataAvailability, l1TxDataAvailability)
 241
 242			tp.zki.ISOutIdx[tp.i] = tp.s.CurrentIdx().BigInt()
 243			tp.zki.ISStateRoot[tp.i] = tp.s.MT.Root().BigInt()
 244			tp.i++
 245		}
 246	}
 247
 248	// remove repeated CoordIdxs that are for the same TokenID (use the
 249	// first occurrence)
 250	usedCoordTokenIDs := make(map[common.TokenID]bool)
 251	var filteredCoordIdxs []common.Idx
 252	for i := 0; i < len(coordIdxs); i++ {
 253		accCoord, err := tp.s.GetAccount(coordIdxs[i])
 254		if err != nil {
 255			return nil, tracerr.Wrap(err)
 256		}
 257		if !usedCoordTokenIDs[accCoord.TokenID] {
 258			usedCoordTokenIDs[accCoord.TokenID] = true
 259			filteredCoordIdxs = append(filteredCoordIdxs, coordIdxs[i])
 260		}
 261	}
 262	coordIdxs = filteredCoordIdxs
 263
 264	tp.AccumulatedFees = make(map[common.Idx]*big.Int)
 265	for _, idx := range coordIdxs {
 266		tp.AccumulatedFees[idx] = big.NewInt(0)
 267	}
 268
 269	// once L1UserTxs & L1CoordinatorTxs are processed, get TokenIDs of
 270	// coordIdxs. In this way, if a coordIdx uses an Idx that is being
 271	// created in the current batch, at this point the Idx will be created
 272	coordIdxsMap, err := tp.s.GetTokenIDsFromIdxs(coordIdxs)
 273	if err != nil {
 274		return nil, tracerr.Wrap(err)
 275	}
 276	// collectedFees will contain the amount of fee collected for each
 277	// TokenID
 278	var collectedFees map[common.TokenID]*big.Int
 279	if tp.s.Type() == statedb.TypeSynchronizer || tp.s.Type() == statedb.TypeBatchBuilder {
 280		collectedFees = make(map[common.TokenID]*big.Int)
 281		for tokenID := range coordIdxsMap {
 282			collectedFees[tokenID] = big.NewInt(0)
 283		}
 284	}
 285
 286	if tp.zki != nil {
 287		// get the feePlanTokens
 288		feePlanTokens, err := tp.getFeePlanTokens(coordIdxs)
 289		if err != nil {
 290			log.Error(err)
 291			return nil, tracerr.Wrap(err)
 292		}
 293		copy(tp.zki.FeePlanTokens, feePlanTokens)
 294	}
 295
 296	// Process L2Txs
 297	for i := 0; i < len(l2txs); i++ {
 298		exitIdx, exitAccount, newExit, err := tp.ProcessL2Tx(coordIdxsMap, collectedFees,
 299			exitTree, &l2txs[i])
 300		if err != nil {
 301			return nil, tracerr.Wrap(err)
 302		}
 303		if tp.zki != nil {
 304			l2TxData, err := l2txs[i].L2Tx().BytesDataAvailability(tp.zki.Metadata.NLevels)
 305			if err != nil {
 306				return nil, tracerr.Wrap(err)
 307			}
 308			tp.zki.Metadata.L2TxsData = append(tp.zki.Metadata.L2TxsData, l2TxData)
 309
 310			// Intermediate States
 311			if tp.i < nTx-1 {
 312				tp.zki.ISOutIdx[tp.i] = tp.s.CurrentIdx().BigInt()
 313				tp.zki.ISStateRoot[tp.i] = tp.s.MT.Root().BigInt()
 314				tp.zki.ISAccFeeOut[tp.i] = formatAccumulatedFees(collectedFees, tp.zki.FeePlanTokens, coordIdxs)
 315				if exitIdx == nil {
 316					tp.zki.ISExitRoot[tp.i] = exitTree.Root().BigInt()
 317				}
 318			}
 319		}
 320		if tp.s.Type() == statedb.TypeSynchronizer || tp.s.Type() == statedb.TypeBatchBuilder {
 321			if exitIdx != nil && exitTree != nil {
 322				exits[tp.i] = processedExit{
 323					exit:    true,
 324					newExit: newExit,
 325					idx:     *exitIdx,
 326					acc:     *exitAccount,
 327				}
 328			}
 329			tp.i++
 330		}
 331	}
 332
 333	if tp.zki != nil {
 334		txCompressedDataEmpty := common.TxCompressedDataEmpty(tp.config.ChainID)
 335		last := tp.i - 1
 336		if tp.i == 0 {
 337			last = 0
 338		}
 339		for i := last; i < int(tp.config.MaxTx); i++ {
 340			if i < int(tp.config.MaxTx)-1 {
 341				tp.zki.ISOutIdx[i] = tp.s.CurrentIdx().BigInt()
 342				tp.zki.ISStateRoot[i] = tp.s.MT.Root().BigInt()
 343				tp.zki.ISAccFeeOut[i] = formatAccumulatedFees(collectedFees,
 344					tp.zki.FeePlanTokens, coordIdxs)
 345				tp.zki.ISExitRoot[i] = exitTree.Root().BigInt()
 346			}
 347			if i >= tp.i {
 348				tp.zki.TxCompressedData[i] = txCompressedDataEmpty
 349			}
 350		}
 351		isFinalAccFee := formatAccumulatedFees(collectedFees, tp.zki.FeePlanTokens, coordIdxs)
 352		copy(tp.zki.ISFinalAccFee, isFinalAccFee)
 353		// before computing the Fees txs, set the ISInitStateRootFee
 354		tp.zki.ISInitStateRootFee = tp.s.MT.Root().BigInt()
 355	}
 356
 357	// distribute the AccumulatedFees from the processed L2Txs into the
 358	// Coordinator Idxs
 359	iFee := 0
 360	for _, idx := range coordIdxs {
 361		accumulatedFee := tp.AccumulatedFees[idx]
 362
 363		// send the fee to the Idx of the Coordinator for the TokenID
 364		// (even if the AccumulatedFee==0, as is how the zk circuit
 365		// works)
 366		accCoord, err := tp.s.GetAccount(idx)
 367		if err != nil {
 368			log.Errorw("Can not distribute accumulated fees to coordinator account: No coord Idx to receive fee", "idx", idx)
 369			return nil, tracerr.Wrap(err)
 370		}
 371		if tp.zki != nil {
 372			tp.zki.TokenID3[iFee] = accCoord.TokenID.BigInt()
 373			tp.zki.Nonce3[iFee] = accCoord.Nonce.BigInt()
 374			coordBJJSign, coordBJJY := babyjub.UnpackSignY(accCoord.BJJ)
 375			if coordBJJSign {
 376				tp.zki.Sign3[iFee] = big.NewInt(1)
 377			}
 378			tp.zki.Ay3[iFee] = coordBJJY
 379			tp.zki.Balance3[iFee] = accCoord.Balance
 380			tp.zki.EthAddr3[iFee] = common.EthAddrToBigInt(accCoord.EthAddr)
 381		}
 382		accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee)
 383		pFee, err := tp.s.UpdateAccount(idx, accCoord)
 384		if err != nil {
 385			log.Error(err)
 386			return nil, tracerr.Wrap(err)
 387		}
 388		if tp.zki != nil {
 389			tp.zki.Siblings3[iFee] = siblingsToZKInputFormat(pFee.Siblings)
 390			tp.zki.ISStateRootFee[iFee] = tp.s.MT.Root().BigInt()
 391		}
 392		iFee++
 393	}
 394	if tp.zki != nil {
 395		for i := len(tp.AccumulatedFees); i < int(tp.config.MaxFeeTx)-1; i++ {
 396			tp.zki.ISStateRootFee[i] = tp.s.MT.Root().BigInt()
 397		}
 398		// add Coord Idx to ZKInputs.FeeTxsData
 399		for i := 0; i < len(coordIdxs); i++ {
 400			tp.zki.FeeIdxs[i] = coordIdxs[i].BigInt()
 401		}
 402	}
 403
 404	if tp.s.Type() == statedb.TypeTxSelector {
 405		return nil, nil
 406	}
 407
 408	// once all txs processed (exitTree root frozen), for each Exit,
 409	// generate common.ExitInfo data
 410	var exitInfos []common.ExitInfo
 411	exitInfosByIdx := make(map[common.Idx]*common.ExitInfo)
 412	for i := 0; i < nTx; i++ {
 413		if !exits[i].exit {
 414			continue
 415		}
 416		exitIdx := exits[i].idx
 417		exitAccount := exits[i].acc
 418
 419		// 0. generate MerkleProof
 420		p, err := exitTree.GenerateSCVerifierProof(exitIdx.BigInt(), nil)
 421		if err != nil {
 422			return nil, tracerr.Wrap(err)
 423		}
 424
 425		// 1. generate common.ExitInfo
 426		ei := common.ExitInfo{
 427			AccountIdx:  exitIdx,
 428			MerkleProof: p,
 429			Balance:     exitAccount.Balance,
 430		}
 431		if prevExit, ok := exitInfosByIdx[exitIdx]; !ok {
 432			exitInfos = append(exitInfos, ei)
 433			exitInfosByIdx[exitIdx] = &exitInfos[len(exitInfos)-1]
 434		} else {
 435			*prevExit = ei
 436		}
 437	}
 438
 439	if tp.s.Type() == statedb.TypeSynchronizer {
 440		// retuTypeexitInfos, createdAccounts and collectedFees, so Synchronizer will
 441		// be able to store it into HistoryDB for the concrete BatchNum
 442		return &ProcessTxOutput{
 443			ZKInputs:           nil,
 444			ExitInfos:          exitInfos,
 445			CreatedAccounts:    createdAccounts,
 446			CoordinatorIdxsMap: coordIdxsMap,
 447			CollectedFees:      collectedFees,
 448		}, nil
 449	}
 450
 451	// compute last ZKInputs parameters
 452	tp.zki.GlobalChainID = big.NewInt(int64(tp.config.ChainID))
 453	tp.zki.Metadata.NewStateRootRaw = tp.s.MT.Root()
 454	tp.zki.Metadata.NewExitRootRaw = exitTree.Root()
 455
 456	// return ZKInputs as the BatchBuilder will return it to forge the Batch
 457	return &ProcessTxOutput{
 458		ZKInputs:           tp.zki,
 459		ExitInfos:          nil,
 460		CreatedAccounts:    nil,
 461		CoordinatorIdxsMap: coordIdxsMap,
 462		CollectedFees:      nil,
 463	}, nil
 464}
 465
 466// getFeePlanTokens returns an array of *big.Int containing a list of tokenIDs
 467// corresponding to the given CoordIdxs and the processed L2Txs
 468func (tp *TxProcessor) getFeePlanTokens(coordIdxs []common.Idx) ([]*big.Int, error) {
 469	var tBI []*big.Int
 470	for i := 0; i < len(coordIdxs); i++ {
 471		acc, err := tp.s.GetAccount(coordIdxs[i])
 472		if err != nil {
 473			log.Errorf("could not get account to determine TokenID of CoordIdx %d not found: %s", coordIdxs[i], err.Error())
 474			return nil, tracerr.Wrap(err)
 475		}
 476		tBI = append(tBI, acc.TokenID.BigInt())
 477	}
 478	return tBI, nil
 479}
 480
 481// ProcessL1Tx process the given L1Tx applying the needed updates to the
 482// StateDB depending on the transaction Type. It returns the 3 parameters
 483// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
 484// the Exit created a new Leaf in the ExitTree.
 485// And another *common.Account parameter which contains the created account in
 486// case that has been a new created account and that the StateDB is of type
 487// TypeSynchronizer.
 488func (tp *TxProcessor) ProcessL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx) (*common.Idx,
 489	*common.Account, bool, *common.Account, error) {
 490	// ZKInputs
 491	if tp.zki != nil {
 492		// Txs
 493		var err error
 494		tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData(tp.config.ChainID)
 495		if err != nil {
 496			log.Error(err)
 497			return nil, nil, false, nil, tracerr.Wrap(err)
 498		}
 499		tp.zki.FromIdx[tp.i] = tx.FromIdx.BigInt()
 500		tp.zki.ToIdx[tp.i] = tx.ToIdx.BigInt()
 501		tp.zki.OnChain[tp.i] = big.NewInt(1)
 502
 503		// L1Txs
 504		depositAmountF40, err := common.NewFloat40(tx.DepositAmount)
 505		if err != nil {
 506			return nil, nil, false, nil, tracerr.Wrap(err)
 507		}
 508		tp.zki.DepositAmountF[tp.i] = big.NewInt(int64(depositAmountF40))
 509		tp.zki.FromEthAddr[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 510		if tx.FromBJJ != common.EmptyBJJComp {
 511			tp.zki.FromBJJCompressed[tp.i] = BJJCompressedTo256BigInts(tx.FromBJJ)
 512		}
 513
 514		// Intermediate States, for all the transactions except for the last one
 515		if tp.i < len(tp.zki.ISOnChain) { // len(tp.zki.ISOnChain) == nTx
 516			tp.zki.ISOnChain[tp.i] = big.NewInt(1)
 517		}
 518	}
 519
 520	switch tx.Type {
 521	case common.TxTypeForceTransfer:
 522		tp.computeEffectiveAmounts(tx)
 523
 524		// go to the MT account of sender and receiver, and update balance
 525		// & nonce
 526
 527		// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees.
 528		// 0 for the parameter toIdx, as at L1Tx ToIdx can only be 0 in
 529		// the Deposit type case.
 530		err := tp.applyTransfer(nil, nil, tx.Tx(), 0)
 531		if err != nil {
 532			log.Error(err)
 533			return nil, nil, false, nil, tracerr.Wrap(err)
 534		}
 535	case common.TxTypeCreateAccountDeposit:
 536		tp.computeEffectiveAmounts(tx)
 537
 538		// add new account to the MT, update balance of the MT account
 539		err := tp.applyCreateAccount(tx)
 540		if err != nil {
 541			log.Error(err)
 542			return nil, nil, false, nil, tracerr.Wrap(err)
 543		}
 544		// TODO applyCreateAccount will return the created account,
 545		// which in the case type==TypeSynchronizer will be added to an
 546		// array of created accounts that will be returned
 547	case common.TxTypeDeposit:
 548		tp.computeEffectiveAmounts(tx)
 549
 550		// update balance of the MT account
 551		err := tp.applyDeposit(tx, false)
 552		if err != nil {
 553			log.Error(err)
 554			return nil, nil, false, nil, tracerr.Wrap(err)
 555		}
 556	case common.TxTypeDepositTransfer:
 557		tp.computeEffectiveAmounts(tx)
 558
 559		// update balance in MT account, update balance & nonce of sender
 560		// & receiver
 561		err := tp.applyDeposit(tx, true)
 562		if err != nil {
 563			log.Error(err)
 564			return nil, nil, false, nil, tracerr.Wrap(err)
 565		}
 566	case common.TxTypeCreateAccountDepositTransfer:
 567		tp.computeEffectiveAmounts(tx)
 568
 569		// add new account to the merkletree, update balance in MT account,
 570		// update balance & nonce of sender & receiver
 571		err := tp.applyCreateAccountDepositTransfer(tx)
 572		if err != nil {
 573			log.Error(err)
 574			return nil, nil, false, nil, tracerr.Wrap(err)
 575		}
 576	case common.TxTypeForceExit:
 577		tp.computeEffectiveAmounts(tx)
 578
 579		// execute exit flow
 580		// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees
 581		exitAccount, newExit, err := tp.applyExit(nil, nil, exitTree, tx.Tx())
 582		if err != nil {
 583			log.Error(err)
 584			return nil, nil, false, nil, tracerr.Wrap(err)
 585		}
 586		return &tx.FromIdx, exitAccount, newExit, nil, nil
 587	default:
 588	}
 589
 590	var createdAccount *common.Account
 591	if tp.s.Type() == statedb.TypeSynchronizer &&
 592		(tx.Type == common.TxTypeCreateAccountDeposit ||
 593			tx.Type == common.TxTypeCreateAccountDepositTransfer) {
 594		var err error
 595		createdAccount, err = tp.s.GetAccount(tp.s.CurrentIdx())
 596		if err != nil {
 597			log.Error(err)
 598			return nil, nil, false, nil, tracerr.Wrap(err)
 599		}
 600	}
 601
 602	return nil, nil, false, createdAccount, nil
 603}
 604
 605// ProcessL2Tx process the given L2Tx applying the needed updates to the
 606// StateDB depending on the transaction Type. It returns the 3 parameters
 607// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
 608// the Exit created a new Leaf in the ExitTree.
 609func (tp *TxProcessor) ProcessL2Tx(coordIdxsMap map[common.TokenID]common.Idx,
 610	collectedFees map[common.TokenID]*big.Int, exitTree *merkletree.MerkleTree,
 611	tx *common.PoolL2Tx) (*common.Idx, *common.Account, bool, error) {
 612	var err error
 613	// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
 614	if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
 615		if tp.s.Type() == statedb.TypeSynchronizer {
 616			// thisTypeould never be reached
 617			log.Error("WARNING: In StateDB with Synchronizer mode L2.ToIdx can't be 0")
 618			return nil, nil, false, tracerr.Wrap(fmt.Errorf("In StateDB with Synchronizer mode L2.ToIdx can't be 0"))
 619		}
 620		// case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ
 621
 622		accSender, err := tp.s.GetAccount(tx.FromIdx)
 623		if err != nil {
 624			return nil, nil, false, tracerr.Wrap(err)
 625		}
 626		tx.AuxToIdx, err = tp.s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ, accSender.TokenID)
 627		if err != nil {
 628			return nil, nil, false, tracerr.Wrap(err)
 629		}
 630	}
 631
 632	// ZKInputs
 633	if tp.zki != nil {
 634		// Txs
 635		tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData(tp.config.ChainID)
 636		if err != nil {
 637			return nil, nil, false, tracerr.Wrap(err)
 638		}
 639		tp.zki.TxCompressedDataV2[tp.i], err = tx.TxCompressedDataV2()
 640		if err != nil {
 641			return nil, nil, false, tracerr.Wrap(err)
 642		}
 643		tp.zki.FromIdx[tp.i] = tx.FromIdx.BigInt()
 644		tp.zki.ToIdx[tp.i] = tx.ToIdx.BigInt()
 645
 646		// fill AuxToIdx if needed
 647		if tx.ToIdx == 0 {
 648			// use toIdx that can have been filled by tx.ToIdx or
 649			// if tx.Idx==0 (this case), toIdx is filled by the Idx
 650			// from db by ToEthAddr&ToBJJ
 651			tp.zki.AuxToIdx[tp.i] = tx.AuxToIdx.BigInt()
 652		}
 653
 654		if tx.ToBJJ != common.EmptyBJJComp {
 655			_, tp.zki.ToBJJAy[tp.i] = babyjub.UnpackSignY(tx.ToBJJ)
 656		}
 657		tp.zki.ToEthAddr[tp.i] = common.EthAddrToBigInt(tx.ToEthAddr)
 658
 659		tp.zki.OnChain[tp.i] = big.NewInt(0)
 660		tp.zki.NewAccount[tp.i] = big.NewInt(0)
 661
 662		// L2Txs
 663		// tp.zki.RqOffset[tp.i] =  // TODO Rq once TxSelector is ready
 664		// tp.zki.RqTxCompressedDataV2[tp.i] = // TODO
 665		// tp.zki.RqToEthAddr[tp.i] = common.EthAddrToBigInt(tx.RqToEthAddr) // TODO
 666		// tp.zki.RqToBJJAy[tp.i] = tx.ToBJJ.Y // TODO
 667
 668		signature, err := tx.Signature.Decompress()
 669		if err != nil {
 670			log.Error(err)
 671			return nil, nil, false, tracerr.Wrap(err)
 672		}
 673		tp.zki.S[tp.i] = signature.S
 674		tp.zki.R8x[tp.i] = signature.R8.X
 675		tp.zki.R8y[tp.i] = signature.R8.Y
 676	}
 677
 678	// if StateDB type==TypeSynchronizer, will need to add Nonce
 679	if tp.s.Type() == statedb.TypeSynchronizer {
 680		// as tType==TypeSynchronizer, always tx.ToIdx!=0
 681		acc, err := tp.s.GetAccount(tx.FromIdx)
 682		if err != nil {
 683			log.Errorw("GetAccount", "fromIdx", tx.FromIdx, "err", err)
 684			return nil, nil, false, tracerr.Wrap(err)
 685		}
 686		tx.Nonce = acc.Nonce
 687		tx.TokenID = acc.TokenID
 688	}
 689
 690	switch tx.Type {
 691	case common.TxTypeTransfer, common.TxTypeTransferToEthAddr, common.TxTypeTransferToBJJ:
 692		// go to the MT account of sender and receiver, and update
 693		// balance & nonce
 694		err = tp.applyTransfer(coordIdxsMap, collectedFees, tx.Tx(), tx.AuxToIdx)
 695		if err != nil {
 696			log.Error(err)
 697			return nil, nil, false, tracerr.Wrap(err)
 698		}
 699	case common.TxTypeExit:
 700		// execute exit flow
 701		exitAccount, newExit, err := tp.applyExit(coordIdxsMap, collectedFees, exitTree, tx.Tx())
 702		if err != nil {
 703			log.Error(err)
 704			return nil, nil, false, tracerr.Wrap(err)
 705		}
 706		return &tx.FromIdx, exitAccount, newExit, nil
 707	default:
 708	}
 709	return nil, nil, false, nil
 710}
 711
 712// applyCreateAccount creates a new account in the account of the depositer, it
 713// stores the deposit value
 714func (tp *TxProcessor) applyCreateAccount(tx *common.L1Tx) error {
 715	account := &common.Account{
 716		TokenID: tx.TokenID,
 717		Nonce:   0,
 718		Balance: tx.EffectiveDepositAmount,
 719		BJJ:     tx.FromBJJ,
 720		EthAddr: tx.FromEthAddr,
 721	}
 722
 723	p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), account)
 724	if err != nil {
 725		return tracerr.Wrap(err)
 726	}
 727	if tp.zki != nil {
 728		tp.zki.TokenID1[tp.i] = tx.TokenID.BigInt()
 729		tp.zki.Nonce1[tp.i] = big.NewInt(0)
 730		fromBJJSign, fromBJJY := babyjub.UnpackSignY(tx.FromBJJ)
 731		if fromBJJSign {
 732			tp.zki.Sign1[tp.i] = big.NewInt(1)
 733		}
 734		tp.zki.Ay1[tp.i] = fromBJJY
 735		tp.zki.Balance1[tp.i] = tx.EffectiveDepositAmount
 736		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 737		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 738		if p.IsOld0 {
 739			tp.zki.IsOld0_1[tp.i] = big.NewInt(1)
 740		}
 741		tp.zki.OldKey1[tp.i] = p.OldKey.BigInt()
 742		tp.zki.OldValue1[tp.i] = p.OldValue.BigInt()
 743
 744		tp.zki.Metadata.NewLastIdxRaw = tp.s.CurrentIdx() + 1
 745
 746		tp.zki.AuxFromIdx[tp.i] = common.Idx(tp.s.CurrentIdx() + 1).BigInt()
 747		tp.zki.NewAccount[tp.i] = big.NewInt(1)
 748
 749		if tp.i < len(tp.zki.ISOnChain) { // len(tp.zki.ISOnChain) == nTx
 750			// intermediate states
 751			tp.zki.ISOnChain[tp.i] = big.NewInt(1)
 752		}
 753	}
 754
 755	return tp.s.SetCurrentIdx(tp.s.CurrentIdx() + 1)
 756}
 757
 758// applyDeposit updates the balance in the account of the depositer, if
 759// andTransfer parameter is set to true, the method will also apply the
 760// Transfer of the L1Tx/DepositTransfer
 761func (tp *TxProcessor) applyDeposit(tx *common.L1Tx, transfer bool) error {
 762	accSender, err := tp.s.GetAccount(tx.FromIdx)
 763	if err != nil {
 764		return tracerr.Wrap(err)
 765	}
 766
 767	if tp.zki != nil {
 768		tp.zki.TokenID1[tp.i] = accSender.TokenID.BigInt()
 769		tp.zki.Nonce1[tp.i] = accSender.Nonce.BigInt()
 770		senderBJJSign, senderBJJY := babyjub.UnpackSignY(accSender.BJJ)
 771		if senderBJJSign {
 772			tp.zki.Sign1[tp.i] = big.NewInt(1)
 773		}
 774		tp.zki.Ay1[tp.i] = senderBJJY
 775		tp.zki.Balance1[tp.i] = accSender.Balance
 776		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(accSender.EthAddr)
 777	}
 778
 779	// add the deposit to the sender
 780	accSender.Balance = new(big.Int).Add(accSender.Balance, tx.EffectiveDepositAmount)
 781	// subtract amount to the sender
 782	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
 783	if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 784		return newErrorNotEnoughBalance(tx.Tx())
 785	}
 786
 787	// update sender account in localStateDB
 788	p, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
 789	if err != nil {
 790		return tracerr.Wrap(err)
 791	}
 792	if tp.zki != nil {
 793		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 794		// IsOld0_1, OldKey1, OldValue1 not needed as this is not an insert
 795	}
 796
 797	// in case that the tx is a L1Tx>DepositTransfer
 798	var accReceiver *common.Account
 799	if transfer {
 800		if tx.ToIdx == tx.FromIdx {
 801			accReceiver = accSender
 802		} else {
 803			accReceiver, err = tp.s.GetAccount(tx.ToIdx)
 804			if err != nil {
 805				return tracerr.Wrap(err)
 806			}
 807		}
 808
 809		if tp.zki != nil {
 810			tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
 811			tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
 812			receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
 813			if receiverBJJSign {
 814				tp.zki.Sign2[tp.i] = big.NewInt(1)
 815			}
 816			tp.zki.Ay2[tp.i] = receiverBJJY
 817			tp.zki.Balance2[tp.i] = accReceiver.Balance
 818			tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
 819		}
 820
 821		// add amount to the receiver
 822		accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
 823
 824		// update receiver account in localStateDB
 825		p, err := tp.s.UpdateAccount(tx.ToIdx, accReceiver)
 826		if err != nil {
 827			return tracerr.Wrap(err)
 828		}
 829		if tp.zki != nil {
 830			tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
 831			// IsOld0_2, OldKey2, OldValue2 not needed as this is not an insert
 832		}
 833	}
 834
 835	return nil
 836}
 837
 838// applyTransfer updates the balance & nonce in the account of the sender, and
 839// the balance in the account of the receiver.
 840// Parameter 'toIdx' should be at 0 if the tx already has tx.ToIdx!=0, if
 841// tx.ToIdx==0, then toIdx!=0, and will be used the toIdx parameter as Idx of
 842// the receiver. This parameter is used when the tx.ToIdx is not specified and
 843// the real ToIdx is found trhrough the ToEthAddr or ToBJJ.
 844func (tp *TxProcessor) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx,
 845	collectedFees map[common.TokenID]*big.Int, tx common.Tx, auxToIdx common.Idx) error {
 846	if auxToIdx == common.Idx(0) {
 847		auxToIdx = tx.ToIdx
 848	}
 849	// get sender and receiver accounts from localStateDB
 850	accSender, err := tp.s.GetAccount(tx.FromIdx)
 851	if err != nil {
 852		log.Error(err)
 853		return tracerr.Wrap(err)
 854	}
 855
 856	if tp.zki != nil {
 857		// Set the State1 before updating the Sender leaf
 858		tp.zki.TokenID1[tp.i] = accSender.TokenID.BigInt()
 859		tp.zki.Nonce1[tp.i] = accSender.Nonce.BigInt()
 860		senderBJJSign, senderBJJY := babyjub.UnpackSignY(accSender.BJJ)
 861		if senderBJJSign {
 862			tp.zki.Sign1[tp.i] = big.NewInt(1)
 863		}
 864		tp.zki.Ay1[tp.i] = senderBJJY
 865		tp.zki.Balance1[tp.i] = accSender.Balance
 866		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(accSender.EthAddr)
 867	}
 868	if !tx.IsL1 { // L2
 869		// increment nonce
 870		accSender.Nonce++
 871
 872		// compute fee and subtract it from the accSender
 873		fee, err := common.CalcFeeAmount(tx.Amount, *tx.Fee)
 874		if err != nil {
 875			return tracerr.Wrap(err)
 876		}
 877		feeAndAmount := new(big.Int).Add(tx.Amount, fee)
 878		accSender.Balance = new(big.Int).Sub(accSender.Balance, feeAndAmount)
 879		if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 880			return newErrorNotEnoughBalance(tx)
 881		}
 882
 883		if _, ok := coordIdxsMap[accSender.TokenID]; ok {
 884			accCoord, err := tp.s.GetAccount(coordIdxsMap[accSender.TokenID])
 885			if err != nil {
 886				return tracerr.Wrap(fmt.Errorf("Can not use CoordIdx that does not exist in the tree. TokenID: %d, CoordIdx: %d", accSender.TokenID, coordIdxsMap[accSender.TokenID]))
 887			}
 888			// accumulate the fee for the Coord account
 889			accumulated := tp.AccumulatedFees[accCoord.Idx]
 890			accumulated.Add(accumulated, fee)
 891
 892			if tp.s.Type() == statedb.TypeSynchronizer ||
 893				tp.s.Type() == statedb.TypeBatchBuilder {
 894				collected := collectedFees[accCoord.TokenID]
 895				collected.Add(collected, fee)
 896			}
 897		} else {
 898			log.Debugw("No coord Idx to receive fee", "tx", tx)
 899		}
 900	} else {
 901		accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
 902		if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 903			return newErrorNotEnoughBalance(tx)
 904		}
 905	}
 906
 907	// update sender account in localStateDB
 908	pSender, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
 909	if err != nil {
 910		log.Error(err)
 911		return tracerr.Wrap(err)
 912	}
 913	if tp.zki != nil {
 914		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(pSender.Siblings)
 915	}
 916
 917	var accReceiver *common.Account
 918	if auxToIdx == tx.FromIdx {
 919		// if Sender is the Receiver, reuse 'accSender' pointer,
 920		// because in the DB the account for 'auxToIdx' won't be
 921		// updated yet
 922		accReceiver = accSender
 923	} else {
 924		accReceiver, err = tp.s.GetAccount(auxToIdx)
 925		if err != nil {
 926			log.Error(err, auxToIdx)
 927			return tracerr.Wrap(err)
 928		}
 929	}
 930	if tp.zki != nil {
 931		// Set the State2 before updating the Receiver leaf
 932		tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
 933		tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
 934		receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
 935		if receiverBJJSign {
 936			tp.zki.Sign2[tp.i] = big.NewInt(1)
 937		}
 938		tp.zki.Ay2[tp.i] = receiverBJJY
 939		tp.zki.Balance2[tp.i] = accReceiver.Balance
 940		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
 941	}
 942
 943	// add amount-feeAmount to the receiver
 944	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
 945
 946	// update receiver account in localStateDB
 947	pReceiver, err := tp.s.UpdateAccount(auxToIdx, accReceiver)
 948	if err != nil {
 949		return tracerr.Wrap(err)
 950	}
 951	if tp.zki != nil {
 952		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(pReceiver.Siblings)
 953	}
 954
 955	return nil
 956}
 957
 958// applyCreateAccountDepositTransfer, in a single tx, creates a new account,
 959// makes a deposit, and performs a transfer to another account
 960func (tp *TxProcessor) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
 961	auxFromIdx := common.Idx(tp.s.CurrentIdx() + 1)
 962	accSender := &common.Account{
 963		TokenID: tx.TokenID,
 964		Nonce:   0,
 965		Balance: tx.EffectiveDepositAmount,
 966		BJJ:     tx.FromBJJ,
 967		EthAddr: tx.FromEthAddr,
 968	}
 969
 970	if tp.zki != nil {
 971		// Set the State1 before updating the Sender leaf
 972		tp.zki.TokenID1[tp.i] = tx.TokenID.BigInt()
 973		tp.zki.Nonce1[tp.i] = big.NewInt(0)
 974		fromBJJSign, fromBJJY := babyjub.UnpackSignY(tx.FromBJJ)
 975		if fromBJJSign {
 976			tp.zki.Sign1[tp.i] = big.NewInt(1)
 977		}
 978		tp.zki.Ay1[tp.i] = fromBJJY
 979		tp.zki.Balance1[tp.i] = tx.EffectiveDepositAmount
 980		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 981	}
 982
 983	// subtract amount to the sender
 984	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
 985	if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 986		return newErrorNotEnoughBalance(tx.Tx())
 987	}
 988
 989	// create Account of the Sender
 990	p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), accSender)
 991	if err != nil {
 992		return tracerr.Wrap(err)
 993	}
 994	if tp.zki != nil {
 995		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 996		if p.IsOld0 {
 997			tp.zki.IsOld0_1[tp.i] = big.NewInt(1)
 998		}
 999		tp.zki.OldKey1[tp.i] = p.OldKey.BigInt()
1000		tp.zki.OldValue1[tp.i] = p.OldValue.BigInt()
1001
1002		tp.zki.Metadata.NewLastIdxRaw = tp.s.CurrentIdx() + 1
1003
1004		tp.zki.AuxFromIdx[tp.i] = auxFromIdx.BigInt()
1005		tp.zki.NewAccount[tp.i] = big.NewInt(1)
1006
1007		// intermediate states
1008		tp.zki.ISOnChain[tp.i] = big.NewInt(1)
1009	}
1010	var accReceiver *common.Account
1011	if tx.ToIdx == auxFromIdx {
1012		accReceiver = accSender
1013	} else {
1014		accReceiver, err = tp.s.GetAccount(tx.ToIdx)
1015		if err != nil {
1016			log.Error(err)
1017			return tracerr.Wrap(err)
1018		}
1019	}
1020
1021	if tp.zki != nil {
1022		// Set the State2 before updating the Receiver leaf
1023		tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
1024		tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
1025		receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
1026		if receiverBJJSign {
1027			tp.zki.Sign2[tp.i] = big.NewInt(1)
1028		}
1029		tp.zki.Ay2[tp.i] = receiverBJJY
1030		tp.zki.Balance2[tp.i] = accReceiver.Balance
1031		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
1032	}
1033
1034	// add amount to the receiver
1035	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
1036
1037	// update receiver account in localStateDB
1038	p, err = tp.s.UpdateAccount(tx.ToIdx, accReceiver)
1039	if err != nil {
1040		return tracerr.Wrap(err)
1041	}
1042	if tp.zki != nil {
1043		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1044	}
1045
1046	return tp.s.SetCurrentIdx(tp.s.CurrentIdx() + 1)
1047}
1048
1049// It returns the ExitAccount and a boolean determining if the Exit created a
1050// new Leaf in the ExitTree.
1051func (tp *TxProcessor) applyExit(coordIdxsMap map[common.TokenID]common.Idx,
1052	collectedFees map[common.TokenID]*big.Int, exitTree *merkletree.MerkleTree,
1053	tx common.Tx) (*common.Account, bool, error) {
1054	// 0. subtract tx.Amount from current Account in StateMT
1055	// add the tx.Amount into the Account (tx.FromIdx) in the ExitMT
1056	acc, err := tp.s.GetAccount(tx.FromIdx)
1057	if err != nil {
1058		return nil, false, tracerr.Wrap(err)
1059	}
1060	if tp.zki != nil {
1061		tp.zki.TokenID1[tp.i] = acc.TokenID.BigInt()
1062		tp.zki.Nonce1[tp.i] = acc.Nonce.BigInt()
1063		accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1064		if accBJJSign {
1065			tp.zki.Sign1[tp.i] = big.NewInt(1)
1066		}
1067		tp.zki.Ay1[tp.i] = accBJJY
1068		tp.zki.Balance1[tp.i] = acc.Balance
1069		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1070	}
1071
1072	if !tx.IsL1 {
1073		// increment nonce
1074		acc.Nonce++
1075
1076		// compute fee and subtract it from the accSender
1077		fee, err := common.CalcFeeAmount(tx.Amount, *tx.Fee)
1078		if err != nil {
1079			return nil, false, tracerr.Wrap(err)
1080		}
1081		feeAndAmount := new(big.Int).Add(tx.Amount, fee)
1082		acc.Balance = new(big.Int).Sub(acc.Balance, feeAndAmount)
1083		if acc.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
1084			return nil, false, newErrorNotEnoughBalance(tx)
1085		}
1086
1087		if _, ok := coordIdxsMap[acc.TokenID]; ok {
1088			accCoord, err := tp.s.GetAccount(coordIdxsMap[acc.TokenID])
1089			if err != nil {
1090				return nil, false, tracerr.Wrap(fmt.Errorf("Can not use CoordIdx that does not exist in the tree. TokenID: %d, CoordIdx: %d", acc.TokenID, coordIdxsMap[acc.TokenID]))
1091			}
1092
1093			// accumulate the fee for the Coord account
1094			accumulated := tp.AccumulatedFees[accCoord.Idx]
1095			accumulated.Add(accumulated, fee)
1096
1097			if tp.s.Type() == statedb.TypeSynchronizer ||
1098				tp.s.Type() == statedb.TypeBatchBuilder {
1099				collected := collectedFees[accCoord.TokenID]
1100				collected.Add(collected, fee)
1101			}
1102		} else {
1103			log.Debugw("No coord Idx to receive fee", "tx", tx)
1104		}
1105	} else {
1106		acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount)
1107		if acc.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
1108			return nil, false, newErrorNotEnoughBalance(tx)
1109		}
1110	}
1111
1112	p, err := tp.s.UpdateAccount(tx.FromIdx, acc)
1113	if err != nil {
1114		return nil, false, tracerr.Wrap(err)
1115	}
1116	if tp.zki != nil {
1117		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
1118	}
1119
1120	if exitTree == nil {
1121		return nil, false, nil
1122	}
1123	exitAccount, err := statedb.GetAccountInTreeDB(exitTree.DB(), tx.FromIdx)
1124	if tracerr.Unwrap(err) == db.ErrNotFound {
1125		// 1a. if idx does not exist in exitTree:
1126		// add new leaf 'ExitTreeLeaf', where ExitTreeLeaf.Balance =
1127		// exitAmount (exitAmount=tx.Amount)
1128		exitAccount := &common.Account{
1129			TokenID: acc.TokenID,
1130			Nonce:   common.Nonce(0),
1131			Balance: tx.Amount,
1132			BJJ:     acc.BJJ,
1133			EthAddr: acc.EthAddr,
1134		}
1135		if tp.zki != nil {
1136			// Set the State2 before creating the Exit leaf
1137			tp.zki.TokenID2[tp.i] = acc.TokenID.BigInt()
1138			tp.zki.Nonce2[tp.i] = big.NewInt(0)
1139			accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1140			if accBJJSign {
1141				tp.zki.Sign2[tp.i] = big.NewInt(1)
1142			}
1143			tp.zki.Ay2[tp.i] = accBJJY
1144			tp.zki.Balance2[tp.i] = tx.Amount
1145			tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1146			// as Leaf didn't exist in the ExitTree, set NewExit[i]=1
1147			tp.zki.NewExit[tp.i] = big.NewInt(1)
1148		}
1149		p, err = statedb.CreateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
1150		if err != nil {
1151			return nil, false, tracerr.Wrap(err)
1152		}
1153		if tp.zki != nil {
1154			tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1155			if p.IsOld0 {
1156				tp.zki.IsOld0_2[tp.i] = big.NewInt(1)
1157			}
1158			tp.zki.OldKey2[tp.i] = p.OldKey.BigInt()
1159			tp.zki.OldValue2[tp.i] = p.OldValue.BigInt()
1160			tp.zki.ISExitRoot[tp.i] = exitTree.Root().BigInt()
1161		}
1162		return exitAccount, true, nil
1163	} else if err != nil {
1164		return exitAccount, false, tracerr.Wrap(err)
1165	}
1166
1167	// 1b. if idx already exist in exitTree:
1168	if tp.zki != nil {
1169		// Set the State2 before updating the Exit leaf
1170		tp.zki.TokenID2[tp.i] = acc.TokenID.BigInt()
1171		// increment nonce from existing ExitLeaf
1172		tp.zki.Nonce2[tp.i] = exitAccount.Nonce.BigInt()
1173		accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1174		if accBJJSign {
1175			tp.zki.Sign2[tp.i] = big.NewInt(1)
1176		}
1177		tp.zki.Ay2[tp.i] = accBJJY
1178		tp.zki.Balance2[tp.i] = tx.Amount
1179		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1180	}
1181
1182	// update account, where account.Balance += exitAmount
1183	exitAccount.Balance = new(big.Int).Add(exitAccount.Balance, tx.Amount)
1184	p, err = statedb.UpdateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
1185	if err != nil {
1186		return nil, false, tracerr.Wrap(err)
1187	}
1188
1189	if tp.zki != nil {
1190		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1191		if p.IsOld0 {
1192			tp.zki.IsOld0_2[tp.i] = big.NewInt(1)
1193		}
1194		tp.zki.OldKey2[tp.i] = p.OldKey.BigInt()
1195		tp.zki.OldValue2[tp.i] = p.OldValue.BigInt()
1196	}
1197
1198	return exitAccount, false, nil
1199}
1200
1201// computeEffectiveAmounts checks that the L1Tx data is correct
1202func (tp *TxProcessor) computeEffectiveAmounts(tx *common.L1Tx) {
1203	tx.EffectiveAmount = tx.Amount
1204	tx.EffectiveDepositAmount = tx.DepositAmount
1205
1206	if !tx.UserOrigin {
1207		// case where the L1Tx is generated by the Coordinator
1208		tx.EffectiveAmount = big.NewInt(0)
1209		tx.EffectiveDepositAmount = big.NewInt(0)
1210		return
1211	}
1212
1213	if tx.Type == common.TxTypeCreateAccountDeposit {
1214		return
1215	}
1216
1217	if tx.ToIdx >= common.UserThreshold && tx.FromIdx == common.Idx(0) {
1218		// CreateAccountDepositTransfer case
1219		cmp := tx.DepositAmount.Cmp(tx.Amount)
1220		if cmp == -1 { // DepositAmount<Amount
1221			tx.EffectiveAmount = big.NewInt(0)
1222			return
1223		}
1224
1225		// check if tx.TokenID==receiver.TokenID
1226		accReceiver, err := tp.s.GetAccount(tx.ToIdx)
1227		if err != nil {
1228			log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.ToIdx: %d", tx.ToIdx)
1229			tx.EffectiveDepositAmount = big.NewInt(0)
1230			tx.EffectiveAmount = big.NewInt(0)
1231			return
1232		}
1233		if tx.TokenID != accReceiver.TokenID {
1234			log.Debugf("EffectiveAmount = 0: tx TokenID (%d) != receiver account TokenID (%d)", tx.TokenID, accReceiver.TokenID)
1235			tx.EffectiveAmount = big.NewInt(0)
1236			return
1237		}
1238		return
1239	}
1240
1241	accSender, err := tp.s.GetAccount(tx.FromIdx)
1242	if err != nil {
1243		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.FromIdx: %d", tx.FromIdx)
1244		tx.EffectiveDepositAmount = big.NewInt(0)
1245		tx.EffectiveAmount = big.NewInt(0)
1246		return
1247	}
1248
1249	// check that tx.TokenID corresponds to the Sender account TokenID
1250	if tx.TokenID != accSender.TokenID {
1251		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: tx.TokenID (%d) !=sender account TokenID (%d)", tx.TokenID, accSender.TokenID)
1252		tx.EffectiveDepositAmount = big.NewInt(0)
1253		tx.EffectiveAmount = big.NewInt(0)
1254		return
1255	}
1256
1257	// check that Sender has enough balance
1258	bal := accSender.Balance
1259	if tx.DepositAmount != nil {
1260		bal = new(big.Int).Add(bal, tx.EffectiveDepositAmount)
1261	}
1262	cmp := bal.Cmp(tx.Amount)
1263	if cmp == -1 {
1264		log.Debugf("EffectiveAmount = 0: Not enough funds (%s<%s)", bal.String(), tx.Amount.String())
1265		tx.EffectiveAmount = big.NewInt(0)
1266		return
1267	}
1268
1269	// check that the tx.FromEthAddr is the same than the EthAddress of the
1270	// Sender
1271	if !bytes.Equal(tx.FromEthAddr.Bytes(), accSender.EthAddr.Bytes()) {
1272		log.Debugf("EffectiveAmount = 0: tx.FromEthAddr (%s) must be the same EthAddr of the sender account by the Idx (%s)", tx.FromEthAddr.Hex(), accSender.EthAddr.Hex())
1273		tx.EffectiveAmount = big.NewInt(0)
1274	}
1275
1276	if tx.ToIdx == common.Idx(1) || tx.ToIdx == common.Idx(0) {
1277		// if transfer is Exit type, there are no more checks
1278		return
1279	}
1280
1281	// check that TokenID is the same for Sender & Receiver account
1282	accReceiver, err := tp.s.GetAccount(tx.ToIdx)
1283	if err != nil {
1284		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.ToIdx: %d", tx.ToIdx)
1285		tx.EffectiveDepositAmount = big.NewInt(0)
1286		tx.EffectiveAmount = big.NewInt(0)
1287		return
1288	}
1289	if accSender.TokenID != accReceiver.TokenID {
1290		log.Debugf("EffectiveAmount = 0: sender account TokenID (%d) != receiver account TokenID (%d)", accSender.TokenID, accReceiver.TokenID)
1291		tx.EffectiveAmount = big.NewInt(0)
1292		return
1293	}
1294	if tx.TokenID != accReceiver.TokenID {
1295		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: tx TokenID (%d) != receiver account TokenID (%d)", tx.TokenID, accReceiver.TokenID)
1296		tx.EffectiveAmount = big.NewInt(0)
1297		return
1298	}
1299}
1300
1301// CheckEnoughBalance returns true if the sender of the transaction has enough
1302// balance in the account to send the Amount+Fee, and also returns the account
1303// Balance and the Fee+Amount (which is used to give information about why the
1304// transaction is not selected in case that this method returns false.
1305func (tp *TxProcessor) CheckEnoughBalance(tx common.PoolL2Tx) (bool, *big.Int, *big.Int) {
1306	acc, err := tp.s.GetAccount(tx.FromIdx)
1307	if err != nil {
1308		return false, nil, nil
1309	}
1310	fee, err := common.CalcFeeAmount(tx.Amount, tx.Fee)
1311	if err != nil {
1312		return false, nil, nil
1313	}
1314	feeAndAmount := new(big.Int).Add(tx.Amount, fee)
1315	return acc.Balance.Cmp(feeAndAmount) != -1, // !=-1 balance<amount
1316		acc.Balance, feeAndAmount
1317}