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