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