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