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