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