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