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