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