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