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