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