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.Typ == 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.Typ == statedb.TypeSynchronizer || tp.s.Typ == 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.Typ == 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.Typ == statedb.TypeSynchronizer || tp.s.Typ == 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.Typ == 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.Typ == statedb.TypeSynchronizer || tp.s.Typ == 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.Typ == statedb.TypeSynchronizer || tp.s.Typ == 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		cmp := accumulatedFee.Cmp(big.NewInt(0))
 364		if cmp == 1 { // accumulatedFee>0
 365			// send the fee to the Idx of the Coordinator for the TokenID
 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		}
 393		iFee++
 394	}
 395	if tp.zki != nil {
 396		for i := len(tp.AccumulatedFees); i < int(tp.config.MaxFeeTx)-1; i++ {
 397			tp.zki.ISStateRootFee[i] = tp.s.MT.Root().BigInt()
 398		}
 399		// add Coord Idx to ZKInputs.FeeTxsData
 400		for i := 0; i < len(coordIdxs); i++ {
 401			tp.zki.FeeIdxs[i] = coordIdxs[i].BigInt()
 402		}
 403	}
 404
 405	if tp.s.Typ == statedb.TypeTxSelector {
 406		return nil, nil
 407	}
 408
 409	// once all txs processed (exitTree root frozen), for each Exit,
 410	// generate common.ExitInfo data
 411	var exitInfos []common.ExitInfo
 412	exitInfosByIdx := make(map[common.Idx]*common.ExitInfo)
 413	for i := 0; i < nTx; i++ {
 414		if !exits[i].exit {
 415			continue
 416		}
 417		exitIdx := exits[i].idx
 418		exitAccount := exits[i].acc
 419
 420		// 0. generate MerkleProof
 421		p, err := exitTree.GenerateSCVerifierProof(exitIdx.BigInt(), nil)
 422		if err != nil {
 423			return nil, tracerr.Wrap(err)
 424		}
 425
 426		// 1. generate common.ExitInfo
 427		ei := common.ExitInfo{
 428			AccountIdx:  exitIdx,
 429			MerkleProof: p,
 430			Balance:     exitAccount.Balance,
 431		}
 432		if prevExit, ok := exitInfosByIdx[exitIdx]; !ok {
 433			exitInfos = append(exitInfos, ei)
 434			exitInfosByIdx[exitIdx] = &exitInfos[len(exitInfos)-1]
 435		} else {
 436			*prevExit = ei
 437		}
 438	}
 439
 440	if tp.s.Typ == statedb.TypeSynchronizer {
 441		// return exitInfos, createdAccounts and collectedFees, so Synchronizer will
 442		// be able to store it into HistoryDB for the concrete BatchNum
 443		return &ProcessTxOutput{
 444			ZKInputs:           nil,
 445			ExitInfos:          exitInfos,
 446			CreatedAccounts:    createdAccounts,
 447			CoordinatorIdxsMap: coordIdxsMap,
 448			CollectedFees:      collectedFees,
 449		}, nil
 450	}
 451
 452	// compute last ZKInputs parameters
 453	tp.zki.GlobalChainID = big.NewInt(int64(tp.config.ChainID))
 454	tp.zki.Metadata.NewStateRootRaw = tp.s.MT.Root()
 455	tp.zki.Metadata.NewExitRootRaw = exitTree.Root()
 456
 457	// return ZKInputs as the BatchBuilder will return it to forge the Batch
 458	return &ProcessTxOutput{
 459		ZKInputs:           tp.zki,
 460		ExitInfos:          nil,
 461		CreatedAccounts:    nil,
 462		CoordinatorIdxsMap: coordIdxsMap,
 463		CollectedFees:      nil,
 464	}, nil
 465}
 466
 467// getFeePlanTokens returns an array of *big.Int containing a list of tokenIDs
 468// corresponding to the given CoordIdxs and the processed L2Txs
 469func (tp *TxProcessor) getFeePlanTokens(coordIdxs []common.Idx) ([]*big.Int, error) {
 470	var tBI []*big.Int
 471	for i := 0; i < len(coordIdxs); i++ {
 472		acc, err := tp.s.GetAccount(coordIdxs[i])
 473		if err != nil {
 474			log.Errorf("could not get account to determine TokenID of CoordIdx %d not found: %s", coordIdxs[i], err.Error())
 475			return nil, tracerr.Wrap(err)
 476		}
 477		tBI = append(tBI, acc.TokenID.BigInt())
 478	}
 479	return tBI, nil
 480}
 481
 482// ProcessL1Tx process the given L1Tx applying the needed updates to the
 483// StateDB depending on the transaction Type. It returns the 3 parameters
 484// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
 485// the Exit created a new Leaf in the ExitTree.
 486// And another *common.Account parameter which contains the created account in
 487// case that has been a new created account and that the StateDB is of type
 488// TypeSynchronizer.
 489func (tp *TxProcessor) ProcessL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx) (*common.Idx,
 490	*common.Account, bool, *common.Account, error) {
 491	// ZKInputs
 492	if tp.zki != nil {
 493		// Txs
 494		var err error
 495		tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData(tp.config.ChainID)
 496		if err != nil {
 497			log.Error(err)
 498			return nil, nil, false, nil, tracerr.Wrap(err)
 499		}
 500		tp.zki.FromIdx[tp.i] = tx.FromIdx.BigInt()
 501		tp.zki.ToIdx[tp.i] = tx.ToIdx.BigInt()
 502		tp.zki.OnChain[tp.i] = big.NewInt(1)
 503
 504		// L1Txs
 505		depositAmountF16, err := common.NewFloat16(tx.DepositAmount)
 506		if err != nil {
 507			return nil, nil, false, nil, tracerr.Wrap(err)
 508		}
 509		tp.zki.DepositAmountF[tp.i] = big.NewInt(int64(depositAmountF16))
 510		tp.zki.FromEthAddr[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 511		if tx.FromBJJ != common.EmptyBJJComp {
 512			tp.zki.FromBJJCompressed[tp.i] = BJJCompressedTo256BigInts(tx.FromBJJ)
 513		}
 514
 515		// Intermediate States, for all the transactions except for the last one
 516		if tp.i < len(tp.zki.ISOnChain) { // len(tp.zki.ISOnChain) == nTx
 517			tp.zki.ISOnChain[tp.i] = big.NewInt(1)
 518		}
 519	}
 520
 521	switch tx.Type {
 522	case common.TxTypeForceTransfer:
 523		tp.computeEffectiveAmounts(tx)
 524
 525		// go to the MT account of sender and receiver, and update balance
 526		// & nonce
 527
 528		// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees.
 529		// 0 for the parameter toIdx, as at L1Tx ToIdx can only be 0 in
 530		// the Deposit type case.
 531		err := tp.applyTransfer(nil, nil, tx.Tx(), 0)
 532		if err != nil {
 533			log.Error(err)
 534			return nil, nil, false, nil, tracerr.Wrap(err)
 535		}
 536	case common.TxTypeCreateAccountDeposit:
 537		tp.computeEffectiveAmounts(tx)
 538
 539		// add new account to the MT, update balance of the MT account
 540		err := tp.applyCreateAccount(tx)
 541		if err != nil {
 542			log.Error(err)
 543			return nil, nil, false, nil, tracerr.Wrap(err)
 544		}
 545		// TODO applyCreateAccount will return the created account,
 546		// which in the case type==TypeSynchronizer will be added to an
 547		// array of created accounts that will be returned
 548	case common.TxTypeDeposit:
 549		tp.computeEffectiveAmounts(tx)
 550
 551		// update balance of the MT account
 552		err := tp.applyDeposit(tx, false)
 553		if err != nil {
 554			log.Error(err)
 555			return nil, nil, false, nil, tracerr.Wrap(err)
 556		}
 557	case common.TxTypeDepositTransfer:
 558		tp.computeEffectiveAmounts(tx)
 559
 560		// update balance in MT account, update balance & nonce of sender
 561		// & receiver
 562		err := tp.applyDeposit(tx, true)
 563		if err != nil {
 564			log.Error(err)
 565			return nil, nil, false, nil, tracerr.Wrap(err)
 566		}
 567	case common.TxTypeCreateAccountDepositTransfer:
 568		tp.computeEffectiveAmounts(tx)
 569
 570		// add new account to the merkletree, update balance in MT account,
 571		// update balance & nonce of sender & receiver
 572		err := tp.applyCreateAccountDepositTransfer(tx)
 573		if err != nil {
 574			log.Error(err)
 575			return nil, nil, false, nil, tracerr.Wrap(err)
 576		}
 577	case common.TxTypeForceExit:
 578		tp.computeEffectiveAmounts(tx)
 579
 580		// execute exit flow
 581		// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees
 582		exitAccount, newExit, err := tp.applyExit(nil, nil, exitTree, tx.Tx())
 583		if err != nil {
 584			log.Error(err)
 585			return nil, nil, false, nil, tracerr.Wrap(err)
 586		}
 587		return &tx.FromIdx, exitAccount, newExit, nil, nil
 588	default:
 589	}
 590
 591	var createdAccount *common.Account
 592	if tp.s.Typ == statedb.TypeSynchronizer &&
 593		(tx.Type == common.TxTypeCreateAccountDeposit ||
 594			tx.Type == common.TxTypeCreateAccountDepositTransfer) {
 595		var err error
 596		createdAccount, err = tp.s.GetAccount(tp.s.CurrentIdx())
 597		if err != nil {
 598			log.Error(err)
 599			return nil, nil, false, nil, tracerr.Wrap(err)
 600		}
 601	}
 602
 603	return nil, nil, false, createdAccount, nil
 604}
 605
 606// ProcessL2Tx process the given L2Tx applying the needed updates to the
 607// StateDB depending on the transaction Type. It returns the 3 parameters
 608// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
 609// the Exit created a new Leaf in the ExitTree.
 610func (tp *TxProcessor) ProcessL2Tx(coordIdxsMap map[common.TokenID]common.Idx,
 611	collectedFees map[common.TokenID]*big.Int, exitTree *merkletree.MerkleTree,
 612	tx *common.PoolL2Tx) (*common.Idx, *common.Account, bool, error) {
 613	var err error
 614	// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
 615	if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
 616		if tp.s.Typ == statedb.TypeSynchronizer {
 617			// this should never be reached
 618			log.Error("WARNING: In StateDB with Synchronizer mode L2.ToIdx can't be 0")
 619			return nil, nil, false, tracerr.Wrap(fmt.Errorf("In StateDB with Synchronizer mode L2.ToIdx can't be 0"))
 620		}
 621		// case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ
 622
 623		accSender, err := tp.s.GetAccount(tx.FromIdx)
 624		if err != nil {
 625			return nil, nil, false, tracerr.Wrap(err)
 626		}
 627		tx.AuxToIdx, err = tp.s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ, accSender.TokenID)
 628		if err != nil {
 629			return nil, nil, false, tracerr.Wrap(err)
 630		}
 631	}
 632
 633	// ZKInputs
 634	if tp.zki != nil {
 635		// Txs
 636		tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData(tp.config.ChainID)
 637		if err != nil {
 638			return nil, nil, false, tracerr.Wrap(err)
 639		}
 640		tp.zki.TxCompressedDataV2[tp.i], err = tx.TxCompressedDataV2()
 641		if err != nil {
 642			return nil, nil, false, tracerr.Wrap(err)
 643		}
 644		tp.zki.FromIdx[tp.i] = tx.FromIdx.BigInt()
 645		tp.zki.ToIdx[tp.i] = tx.ToIdx.BigInt()
 646
 647		// fill AuxToIdx if needed
 648		if tx.ToIdx == 0 {
 649			// use toIdx that can have been filled by tx.ToIdx or
 650			// if tx.Idx==0 (this case), toIdx is filled by the Idx
 651			// from db by ToEthAddr&ToBJJ
 652			tp.zki.AuxToIdx[tp.i] = tx.AuxToIdx.BigInt()
 653		}
 654
 655		if tx.ToBJJ != common.EmptyBJJComp {
 656			_, tp.zki.ToBJJAy[tp.i] = babyjub.UnpackSignY(tx.ToBJJ)
 657		}
 658		tp.zki.ToEthAddr[tp.i] = common.EthAddrToBigInt(tx.ToEthAddr)
 659
 660		tp.zki.OnChain[tp.i] = big.NewInt(0)
 661		tp.zki.NewAccount[tp.i] = big.NewInt(0)
 662
 663		// L2Txs
 664		// tp.zki.RqOffset[tp.i] =  // TODO Rq once TxSelector is ready
 665		// tp.zki.RqTxCompressedDataV2[tp.i] = // TODO
 666		// tp.zki.RqToEthAddr[tp.i] = common.EthAddrToBigInt(tx.RqToEthAddr) // TODO
 667		// tp.zki.RqToBJJAy[tp.i] = tx.ToBJJ.Y // TODO
 668
 669		signature, err := tx.Signature.Decompress()
 670		if err != nil {
 671			log.Error(err)
 672			return nil, nil, false, tracerr.Wrap(err)
 673		}
 674		tp.zki.S[tp.i] = signature.S
 675		tp.zki.R8x[tp.i] = signature.R8.X
 676		tp.zki.R8y[tp.i] = signature.R8.Y
 677	}
 678
 679	// if StateDB type==TypeSynchronizer, will need to add Nonce
 680	if tp.s.Typ == statedb.TypeSynchronizer {
 681		// as type==TypeSynchronizer, always tx.ToIdx!=0
 682		acc, err := tp.s.GetAccount(tx.FromIdx)
 683		if err != nil {
 684			log.Errorw("GetAccount", "fromIdx", tx.FromIdx, "err", err)
 685			return nil, nil, false, tracerr.Wrap(err)
 686		}
 687		tx.Nonce = acc.Nonce
 688		tx.TokenID = acc.TokenID
 689	}
 690
 691	switch tx.Type {
 692	case common.TxTypeTransfer, common.TxTypeTransferToEthAddr, common.TxTypeTransferToBJJ:
 693		// go to the MT account of sender and receiver, and update
 694		// balance & nonce
 695		err = tp.applyTransfer(coordIdxsMap, collectedFees, tx.Tx(), tx.AuxToIdx)
 696		if err != nil {
 697			log.Error(err)
 698			return nil, nil, false, tracerr.Wrap(err)
 699		}
 700	case common.TxTypeExit:
 701		// execute exit flow
 702		exitAccount, newExit, err := tp.applyExit(coordIdxsMap, collectedFees, exitTree, tx.Tx())
 703		if err != nil {
 704			log.Error(err)
 705			return nil, nil, false, tracerr.Wrap(err)
 706		}
 707		return &tx.FromIdx, exitAccount, newExit, nil
 708	default:
 709	}
 710	return nil, nil, false, nil
 711}
 712
 713// applyCreateAccount creates a new account in the account of the depositer, it
 714// stores the deposit value
 715func (tp *TxProcessor) applyCreateAccount(tx *common.L1Tx) error {
 716	account := &common.Account{
 717		TokenID: tx.TokenID,
 718		Nonce:   0,
 719		Balance: tx.EffectiveDepositAmount,
 720		BJJ:     tx.FromBJJ,
 721		EthAddr: tx.FromEthAddr,
 722	}
 723
 724	p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), account)
 725	if err != nil {
 726		return tracerr.Wrap(err)
 727	}
 728	if tp.zki != nil {
 729		tp.zki.TokenID1[tp.i] = tx.TokenID.BigInt()
 730		tp.zki.Nonce1[tp.i] = big.NewInt(0)
 731		fromBJJSign, fromBJJY := babyjub.UnpackSignY(tx.FromBJJ)
 732		if fromBJJSign {
 733			tp.zki.Sign1[tp.i] = big.NewInt(1)
 734		}
 735		tp.zki.Ay1[tp.i] = fromBJJY
 736		tp.zki.Balance1[tp.i] = tx.EffectiveDepositAmount
 737		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 738		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 739		if p.IsOld0 {
 740			tp.zki.IsOld0_1[tp.i] = big.NewInt(1)
 741		}
 742		tp.zki.OldKey1[tp.i] = p.OldKey.BigInt()
 743		tp.zki.OldValue1[tp.i] = p.OldValue.BigInt()
 744
 745		tp.zki.Metadata.NewLastIdxRaw = tp.s.CurrentIdx() + 1
 746
 747		tp.zki.AuxFromIdx[tp.i] = common.Idx(tp.s.CurrentIdx() + 1).BigInt()
 748		tp.zki.NewAccount[tp.i] = big.NewInt(1)
 749
 750		if tp.i < len(tp.zki.ISOnChain) { // len(tp.zki.ISOnChain) == nTx
 751			// intermediate states
 752			tp.zki.ISOnChain[tp.i] = big.NewInt(1)
 753		}
 754	}
 755
 756	return tp.s.SetCurrentIdx(tp.s.CurrentIdx() + 1)
 757}
 758
 759// applyDeposit updates the balance in the account of the depositer, if
 760// andTransfer parameter is set to true, the method will also apply the
 761// Transfer of the L1Tx/DepositTransfer
 762func (tp *TxProcessor) applyDeposit(tx *common.L1Tx, transfer bool) error {
 763	accSender, err := tp.s.GetAccount(tx.FromIdx)
 764	if err != nil {
 765		return tracerr.Wrap(err)
 766	}
 767
 768	if tp.zki != nil {
 769		tp.zki.TokenID1[tp.i] = accSender.TokenID.BigInt()
 770		tp.zki.Nonce1[tp.i] = accSender.Nonce.BigInt()
 771		senderBJJSign, senderBJJY := babyjub.UnpackSignY(accSender.BJJ)
 772		if senderBJJSign {
 773			tp.zki.Sign1[tp.i] = big.NewInt(1)
 774		}
 775		tp.zki.Ay1[tp.i] = senderBJJY
 776		tp.zki.Balance1[tp.i] = accSender.Balance
 777		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(accSender.EthAddr)
 778	}
 779
 780	// add the deposit to the sender
 781	accSender.Balance = new(big.Int).Add(accSender.Balance, tx.EffectiveDepositAmount)
 782	// subtract amount to the sender
 783	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
 784	if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 785		return newErrorNotEnoughBalance(tx.Tx())
 786	}
 787
 788	// update sender account in localStateDB
 789	p, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
 790	if err != nil {
 791		return tracerr.Wrap(err)
 792	}
 793	if tp.zki != nil {
 794		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 795		// IsOld0_1, OldKey1, OldValue1 not needed as this is not an insert
 796	}
 797
 798	// in case that the tx is a L1Tx>DepositTransfer
 799	var accReceiver *common.Account
 800	if transfer {
 801		if tx.ToIdx == tx.FromIdx {
 802			accReceiver = accSender
 803		} else {
 804			accReceiver, err = tp.s.GetAccount(tx.ToIdx)
 805			if err != nil {
 806				return tracerr.Wrap(err)
 807			}
 808		}
 809
 810		if tp.zki != nil {
 811			tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
 812			tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
 813			receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
 814			if receiverBJJSign {
 815				tp.zki.Sign2[tp.i] = big.NewInt(1)
 816			}
 817			tp.zki.Ay2[tp.i] = receiverBJJY
 818			tp.zki.Balance2[tp.i] = accReceiver.Balance
 819			tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
 820		}
 821
 822		// add amount to the receiver
 823		accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
 824
 825		// update receiver account in localStateDB
 826		p, err := tp.s.UpdateAccount(tx.ToIdx, accReceiver)
 827		if err != nil {
 828			return tracerr.Wrap(err)
 829		}
 830		if tp.zki != nil {
 831			tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
 832			// IsOld0_2, OldKey2, OldValue2 not needed as this is not an insert
 833		}
 834	}
 835
 836	return nil
 837}
 838
 839// applyTransfer updates the balance & nonce in the account of the sender, and
 840// the balance in the account of the receiver.
 841// Parameter 'toIdx' should be at 0 if the tx already has tx.ToIdx!=0, if
 842// tx.ToIdx==0, then toIdx!=0, and will be used the toIdx parameter as Idx of
 843// the receiver. This parameter is used when the tx.ToIdx is not specified and
 844// the real ToIdx is found trhrough the ToEthAddr or ToBJJ.
 845func (tp *TxProcessor) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx,
 846	collectedFees map[common.TokenID]*big.Int, tx common.Tx, auxToIdx common.Idx) error {
 847	if auxToIdx == common.Idx(0) {
 848		auxToIdx = tx.ToIdx
 849	}
 850	// get sender and receiver accounts from localStateDB
 851	accSender, err := tp.s.GetAccount(tx.FromIdx)
 852	if err != nil {
 853		log.Error(err)
 854		return tracerr.Wrap(err)
 855	}
 856
 857	if tp.zki != nil {
 858		// Set the State1 before updating the Sender leaf
 859		tp.zki.TokenID1[tp.i] = accSender.TokenID.BigInt()
 860		tp.zki.Nonce1[tp.i] = accSender.Nonce.BigInt()
 861		senderBJJSign, senderBJJY := babyjub.UnpackSignY(accSender.BJJ)
 862		if senderBJJSign {
 863			tp.zki.Sign1[tp.i] = big.NewInt(1)
 864		}
 865		tp.zki.Ay1[tp.i] = senderBJJY
 866		tp.zki.Balance1[tp.i] = accSender.Balance
 867		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(accSender.EthAddr)
 868	}
 869	if !tx.IsL1 { // L2
 870		// increment nonce
 871		accSender.Nonce++
 872
 873		// compute fee and subtract it from the accSender
 874		fee, err := common.CalcFeeAmount(tx.Amount, *tx.Fee)
 875		if err != nil {
 876			return tracerr.Wrap(err)
 877		}
 878		feeAndAmount := new(big.Int).Add(tx.Amount, fee)
 879		accSender.Balance = new(big.Int).Sub(accSender.Balance, feeAndAmount)
 880		if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 881			return newErrorNotEnoughBalance(tx)
 882		}
 883
 884		if _, ok := coordIdxsMap[accSender.TokenID]; ok {
 885			accCoord, err := tp.s.GetAccount(coordIdxsMap[accSender.TokenID])
 886			if err != nil {
 887				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]))
 888			}
 889			// accumulate the fee for the Coord account
 890			accumulated := tp.AccumulatedFees[accCoord.Idx]
 891			accumulated.Add(accumulated, fee)
 892
 893			if tp.s.Typ == statedb.TypeSynchronizer ||
 894				tp.s.Typ == statedb.TypeBatchBuilder {
 895				collected := collectedFees[accCoord.TokenID]
 896				collected.Add(collected, fee)
 897			}
 898		} else {
 899			log.Debugw("No coord Idx to receive fee", "tx", tx)
 900		}
 901	} else {
 902		accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
 903		if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 904			return newErrorNotEnoughBalance(tx)
 905		}
 906	}
 907
 908	// update sender account in localStateDB
 909	pSender, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
 910	if err != nil {
 911		log.Error(err)
 912		return tracerr.Wrap(err)
 913	}
 914	if tp.zki != nil {
 915		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(pSender.Siblings)
 916	}
 917
 918	var accReceiver *common.Account
 919	if auxToIdx == tx.FromIdx {
 920		// if Sender is the Receiver, reuse 'accSender' pointer,
 921		// because in the DB the account for 'auxToIdx' won't be
 922		// updated yet
 923		accReceiver = accSender
 924	} else {
 925		accReceiver, err = tp.s.GetAccount(auxToIdx)
 926		if err != nil {
 927			log.Error(err, auxToIdx)
 928			return tracerr.Wrap(err)
 929		}
 930	}
 931	if tp.zki != nil {
 932		// Set the State2 before updating the Receiver leaf
 933		tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
 934		tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
 935		receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
 936		if receiverBJJSign {
 937			tp.zki.Sign2[tp.i] = big.NewInt(1)
 938		}
 939		tp.zki.Ay2[tp.i] = receiverBJJY
 940		tp.zki.Balance2[tp.i] = accReceiver.Balance
 941		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
 942	}
 943
 944	// add amount-feeAmount to the receiver
 945	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
 946
 947	// update receiver account in localStateDB
 948	pReceiver, err := tp.s.UpdateAccount(auxToIdx, accReceiver)
 949	if err != nil {
 950		return tracerr.Wrap(err)
 951	}
 952	if tp.zki != nil {
 953		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(pReceiver.Siblings)
 954	}
 955
 956	return nil
 957}
 958
 959// applyCreateAccountDepositTransfer, in a single tx, creates a new account,
 960// makes a deposit, and performs a transfer to another account
 961func (tp *TxProcessor) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
 962	auxFromIdx := common.Idx(tp.s.CurrentIdx() + 1)
 963	accSender := &common.Account{
 964		TokenID: tx.TokenID,
 965		Nonce:   0,
 966		Balance: tx.EffectiveDepositAmount,
 967		BJJ:     tx.FromBJJ,
 968		EthAddr: tx.FromEthAddr,
 969	}
 970
 971	if tp.zki != nil {
 972		// Set the State1 before updating the Sender leaf
 973		tp.zki.TokenID1[tp.i] = tx.TokenID.BigInt()
 974		tp.zki.Nonce1[tp.i] = big.NewInt(0)
 975		fromBJJSign, fromBJJY := babyjub.UnpackSignY(tx.FromBJJ)
 976		if fromBJJSign {
 977			tp.zki.Sign1[tp.i] = big.NewInt(1)
 978		}
 979		tp.zki.Ay1[tp.i] = fromBJJY
 980		tp.zki.Balance1[tp.i] = tx.EffectiveDepositAmount
 981		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(tx.FromEthAddr)
 982	}
 983
 984	// subtract amount to the sender
 985	accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
 986	if accSender.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
 987		return newErrorNotEnoughBalance(tx.Tx())
 988	}
 989
 990	// create Account of the Sender
 991	p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), accSender)
 992	if err != nil {
 993		return tracerr.Wrap(err)
 994	}
 995	if tp.zki != nil {
 996		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
 997		if p.IsOld0 {
 998			tp.zki.IsOld0_1[tp.i] = big.NewInt(1)
 999		}
1000		tp.zki.OldKey1[tp.i] = p.OldKey.BigInt()
1001		tp.zki.OldValue1[tp.i] = p.OldValue.BigInt()
1002
1003		tp.zki.Metadata.NewLastIdxRaw = tp.s.CurrentIdx() + 1
1004
1005		tp.zki.AuxFromIdx[tp.i] = auxFromIdx.BigInt()
1006		tp.zki.NewAccount[tp.i] = big.NewInt(1)
1007
1008		// intermediate states
1009		tp.zki.ISOnChain[tp.i] = big.NewInt(1)
1010	}
1011	var accReceiver *common.Account
1012	if tx.ToIdx == auxFromIdx {
1013		accReceiver = accSender
1014	} else {
1015		accReceiver, err = tp.s.GetAccount(tx.ToIdx)
1016		if err != nil {
1017			log.Error(err)
1018			return tracerr.Wrap(err)
1019		}
1020	}
1021
1022	if tp.zki != nil {
1023		// Set the State2 before updating the Receiver leaf
1024		tp.zki.TokenID2[tp.i] = accReceiver.TokenID.BigInt()
1025		tp.zki.Nonce2[tp.i] = accReceiver.Nonce.BigInt()
1026		receiverBJJSign, receiverBJJY := babyjub.UnpackSignY(accReceiver.BJJ)
1027		if receiverBJJSign {
1028			tp.zki.Sign2[tp.i] = big.NewInt(1)
1029		}
1030		tp.zki.Ay2[tp.i] = receiverBJJY
1031		tp.zki.Balance2[tp.i] = accReceiver.Balance
1032		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(accReceiver.EthAddr)
1033	}
1034
1035	// add amount to the receiver
1036	accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
1037
1038	// update receiver account in localStateDB
1039	p, err = tp.s.UpdateAccount(tx.ToIdx, accReceiver)
1040	if err != nil {
1041		return tracerr.Wrap(err)
1042	}
1043	if tp.zki != nil {
1044		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1045	}
1046
1047	return tp.s.SetCurrentIdx(tp.s.CurrentIdx() + 1)
1048}
1049
1050// It returns the ExitAccount and a boolean determining if the Exit created a
1051// new Leaf in the ExitTree.
1052func (tp *TxProcessor) applyExit(coordIdxsMap map[common.TokenID]common.Idx,
1053	collectedFees map[common.TokenID]*big.Int, exitTree *merkletree.MerkleTree,
1054	tx common.Tx) (*common.Account, bool, error) {
1055	// 0. subtract tx.Amount from current Account in StateMT
1056	// add the tx.Amount into the Account (tx.FromIdx) in the ExitMT
1057	acc, err := tp.s.GetAccount(tx.FromIdx)
1058	if err != nil {
1059		return nil, false, tracerr.Wrap(err)
1060	}
1061	if tp.zki != nil {
1062		tp.zki.TokenID1[tp.i] = acc.TokenID.BigInt()
1063		tp.zki.Nonce1[tp.i] = acc.Nonce.BigInt()
1064		accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1065		if accBJJSign {
1066			tp.zki.Sign1[tp.i] = big.NewInt(1)
1067		}
1068		tp.zki.Ay1[tp.i] = accBJJY
1069		tp.zki.Balance1[tp.i] = acc.Balance
1070		tp.zki.EthAddr1[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1071	}
1072
1073	if !tx.IsL1 {
1074		// increment nonce
1075		acc.Nonce++
1076
1077		// compute fee and subtract it from the accSender
1078		fee, err := common.CalcFeeAmount(tx.Amount, *tx.Fee)
1079		if err != nil {
1080			return nil, false, tracerr.Wrap(err)
1081		}
1082		feeAndAmount := new(big.Int).Add(tx.Amount, fee)
1083		acc.Balance = new(big.Int).Sub(acc.Balance, feeAndAmount)
1084		if acc.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
1085			return nil, false, newErrorNotEnoughBalance(tx)
1086		}
1087
1088		if _, ok := coordIdxsMap[acc.TokenID]; ok {
1089			accCoord, err := tp.s.GetAccount(coordIdxsMap[acc.TokenID])
1090			if err != nil {
1091				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]))
1092			}
1093
1094			// accumulate the fee for the Coord account
1095			accumulated := tp.AccumulatedFees[accCoord.Idx]
1096			accumulated.Add(accumulated, fee)
1097
1098			if tp.s.Typ == statedb.TypeSynchronizer ||
1099				tp.s.Typ == statedb.TypeBatchBuilder {
1100				collected := collectedFees[accCoord.TokenID]
1101				collected.Add(collected, fee)
1102			}
1103		} else {
1104			log.Debugw("No coord Idx to receive fee", "tx", tx)
1105		}
1106	} else {
1107		acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount)
1108		if acc.Balance.Cmp(big.NewInt(0)) == -1 { // balance<0
1109			return nil, false, newErrorNotEnoughBalance(tx)
1110		}
1111	}
1112
1113	p, err := tp.s.UpdateAccount(tx.FromIdx, acc)
1114	if err != nil {
1115		return nil, false, tracerr.Wrap(err)
1116	}
1117	if tp.zki != nil {
1118		tp.zki.Siblings1[tp.i] = siblingsToZKInputFormat(p.Siblings)
1119	}
1120
1121	if exitTree == nil {
1122		return nil, false, nil
1123	}
1124	exitAccount, err := statedb.GetAccountInTreeDB(exitTree.DB(), tx.FromIdx)
1125	if tracerr.Unwrap(err) == db.ErrNotFound {
1126		// 1a. if idx does not exist in exitTree:
1127		// add new leaf 'ExitTreeLeaf', where ExitTreeLeaf.Balance =
1128		// exitAmount (exitAmount=tx.Amount)
1129		exitAccount := &common.Account{
1130			TokenID: acc.TokenID,
1131			Nonce:   common.Nonce(0),
1132			Balance: tx.Amount,
1133			BJJ:     acc.BJJ,
1134			EthAddr: acc.EthAddr,
1135		}
1136		if tp.zki != nil {
1137			// Set the State2 before creating the Exit leaf
1138			tp.zki.TokenID2[tp.i] = acc.TokenID.BigInt()
1139			tp.zki.Nonce2[tp.i] = big.NewInt(0)
1140			accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1141			if accBJJSign {
1142				tp.zki.Sign2[tp.i] = big.NewInt(1)
1143			}
1144			tp.zki.Ay2[tp.i] = accBJJY
1145			tp.zki.Balance2[tp.i] = tx.Amount
1146			tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1147			// as Leaf didn't exist in the ExitTree, set NewExit[i]=1
1148			tp.zki.NewExit[tp.i] = big.NewInt(1)
1149		}
1150		p, err = statedb.CreateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
1151		if err != nil {
1152			return nil, false, tracerr.Wrap(err)
1153		}
1154		if tp.zki != nil {
1155			tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1156			if p.IsOld0 {
1157				tp.zki.IsOld0_2[tp.i] = big.NewInt(1)
1158			}
1159			tp.zki.OldKey2[tp.i] = p.OldKey.BigInt()
1160			tp.zki.OldValue2[tp.i] = p.OldValue.BigInt()
1161			tp.zki.ISExitRoot[tp.i] = exitTree.Root().BigInt()
1162		}
1163		return exitAccount, true, nil
1164	} else if err != nil {
1165		return exitAccount, false, tracerr.Wrap(err)
1166	}
1167
1168	// 1b. if idx already exist in exitTree:
1169	if tp.zki != nil {
1170		// Set the State2 before updating the Exit leaf
1171		tp.zki.TokenID2[tp.i] = acc.TokenID.BigInt()
1172		// increment nonce from existing ExitLeaf
1173		tp.zki.Nonce2[tp.i] = exitAccount.Nonce.BigInt()
1174		accBJJSign, accBJJY := babyjub.UnpackSignY(acc.BJJ)
1175		if accBJJSign {
1176			tp.zki.Sign2[tp.i] = big.NewInt(1)
1177		}
1178		tp.zki.Ay2[tp.i] = accBJJY
1179		tp.zki.Balance2[tp.i] = tx.Amount
1180		tp.zki.EthAddr2[tp.i] = common.EthAddrToBigInt(acc.EthAddr)
1181	}
1182
1183	// update account, where account.Balance += exitAmount
1184	exitAccount.Balance = new(big.Int).Add(exitAccount.Balance, tx.Amount)
1185	p, err = statedb.UpdateAccountInTreeDB(exitTree.DB(), exitTree, tx.FromIdx, exitAccount)
1186	if err != nil {
1187		return nil, false, tracerr.Wrap(err)
1188	}
1189
1190	if tp.zki != nil {
1191		tp.zki.Siblings2[tp.i] = siblingsToZKInputFormat(p.Siblings)
1192		if p.IsOld0 {
1193			tp.zki.IsOld0_2[tp.i] = big.NewInt(1)
1194		}
1195		tp.zki.OldKey2[tp.i] = p.OldKey.BigInt()
1196		tp.zki.OldValue2[tp.i] = p.OldValue.BigInt()
1197	}
1198
1199	return exitAccount, false, nil
1200}
1201
1202// computeEffectiveAmounts checks that the L1Tx data is correct
1203func (tp *TxProcessor) computeEffectiveAmounts(tx *common.L1Tx) {
1204	tx.EffectiveAmount = tx.Amount
1205	tx.EffectiveDepositAmount = tx.DepositAmount
1206
1207	if !tx.UserOrigin {
1208		// case where the L1Tx is generated by the Coordinator
1209		tx.EffectiveAmount = big.NewInt(0)
1210		tx.EffectiveDepositAmount = big.NewInt(0)
1211		return
1212	}
1213
1214	if tx.Type == common.TxTypeCreateAccountDeposit {
1215		return
1216	}
1217
1218	if tx.ToIdx >= common.UserThreshold && tx.FromIdx == common.Idx(0) {
1219		// CreateAccountDepositTransfer case
1220		cmp := tx.DepositAmount.Cmp(tx.Amount)
1221		if cmp == -1 { // DepositAmount<Amount
1222			tx.EffectiveAmount = big.NewInt(0)
1223			return
1224		}
1225
1226		// check if tx.TokenID==receiver.TokenID
1227		accReceiver, err := tp.s.GetAccount(tx.ToIdx)
1228		if err != nil {
1229			log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.ToIdx: %d", tx.ToIdx)
1230			tx.EffectiveDepositAmount = big.NewInt(0)
1231			tx.EffectiveAmount = big.NewInt(0)
1232			return
1233		}
1234		if tx.TokenID != accReceiver.TokenID {
1235			log.Debugf("EffectiveAmount = 0: tx TokenID (%d) != receiver account TokenID (%d)", tx.TokenID, accReceiver.TokenID)
1236			tx.EffectiveAmount = big.NewInt(0)
1237			return
1238		}
1239		return
1240	}
1241
1242	accSender, err := tp.s.GetAccount(tx.FromIdx)
1243	if err != nil {
1244		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.FromIdx: %d", tx.FromIdx)
1245		tx.EffectiveDepositAmount = big.NewInt(0)
1246		tx.EffectiveAmount = big.NewInt(0)
1247		return
1248	}
1249
1250	// check that tx.TokenID corresponds to the Sender account TokenID
1251	if tx.TokenID != accSender.TokenID {
1252		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: tx.TokenID (%d) !=sender account TokenID (%d)", tx.TokenID, accSender.TokenID)
1253		tx.EffectiveDepositAmount = big.NewInt(0)
1254		tx.EffectiveAmount = big.NewInt(0)
1255		return
1256	}
1257
1258	// check that Sender has enough balance
1259	bal := accSender.Balance
1260	if tx.DepositAmount != nil {
1261		bal = new(big.Int).Add(bal, tx.EffectiveDepositAmount)
1262	}
1263	cmp := bal.Cmp(tx.Amount)
1264	if cmp == -1 {
1265		log.Debugf("EffectiveAmount = 0: Not enough funds (%s<%s)", bal.String(), tx.Amount.String())
1266		tx.EffectiveAmount = big.NewInt(0)
1267		return
1268	}
1269
1270	// check that the tx.FromEthAddr is the same than the EthAddress of the
1271	// Sender
1272	if !bytes.Equal(tx.FromEthAddr.Bytes(), accSender.EthAddr.Bytes()) {
1273		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())
1274		tx.EffectiveAmount = big.NewInt(0)
1275	}
1276
1277	if tx.ToIdx == common.Idx(1) || tx.ToIdx == common.Idx(0) {
1278		// if transfer is Exit type, there are no more checks
1279		return
1280	}
1281
1282	// check that TokenID is the same for Sender & Receiver account
1283	accReceiver, err := tp.s.GetAccount(tx.ToIdx)
1284	if err != nil {
1285		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: can not get account for tx.ToIdx: %d", tx.ToIdx)
1286		tx.EffectiveDepositAmount = big.NewInt(0)
1287		tx.EffectiveAmount = big.NewInt(0)
1288		return
1289	}
1290	if accSender.TokenID != accReceiver.TokenID {
1291		log.Debugf("EffectiveAmount = 0: sender account TokenID (%d) != receiver account TokenID (%d)", accSender.TokenID, accReceiver.TokenID)
1292		tx.EffectiveAmount = big.NewInt(0)
1293		return
1294	}
1295	if tx.TokenID != accReceiver.TokenID {
1296		log.Debugf("EffectiveAmount & EffectiveDepositAmount = 0: tx TokenID (%d) != receiver account TokenID (%d)", tx.TokenID, accReceiver.TokenID)
1297		tx.EffectiveAmount = big.NewInt(0)
1298		return
1299	}
1300}
1301
1302// CheckEnoughBalance returns true if the sender of the transaction has enough
1303// balance in the account to send the Amount+Fee
1304func (tp *TxProcessor) CheckEnoughBalance(tx common.PoolL2Tx) bool {
1305	acc, err := tp.s.GetAccount(tx.FromIdx)
1306	if err != nil {
1307		return false
1308	}
1309	fee, err := common.CalcFeeAmount(tx.Amount, tx.Fee)
1310	if err != nil {
1311		return false
1312	}
1313	feeAndAmount := new(big.Int).Add(tx.Amount, fee)
1314	return acc.Balance.Cmp(feeAndAmount) != -1 // !=-1 balance<amount
1315}