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