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