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