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