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