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