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