@ -16,13 +16,6 @@ import (
"github.com/hermeznetwork/hermez-node/txprocessor"
"github.com/hermeznetwork/tracerr"
"github.com/iden3/go-iden3-crypto/babyjub"
"github.com/iden3/go-merkletree/db"
)
const (
// PathCoordIdxsDB defines the path of the key-value db where the
// CoordIdxs will be stored
PathCoordIdxsDB = "/coordidxs"
)
// txs implements the interface Sort for an array of Tx
@ -44,7 +37,7 @@ func (t txs) Less(i, j int) bool {
type CoordAccount struct {
Addr ethCommon . Address
BJJ babyjub . PublicKeyComp
AccountCreationAuth [ ] byte
AccountCreationAuth [ ] byte // signature in byte array format
}
// SelectionConfig contains the parameters of configuration of the selection of
@ -52,8 +45,6 @@ type CoordAccount struct {
type SelectionConfig struct {
// MaxL1UserTxs is the maximum L1-user-tx for a batch
MaxL1UserTxs uint64
// MaxL1CoordinatorTxs is the maximum L1-coordinator-tx for a batch
MaxL1CoordinatorTxs uint64
// TxProcessorConfig contains the config for ProcessTxs
TxProcessorConfig txprocessor . Config
@ -100,7 +91,8 @@ func (txsel *TxSelector) Reset(batchNum common.BatchNum) error {
}
func ( txsel * TxSelector ) getCoordIdx ( tokenID common . TokenID ) ( common . Idx , error ) {
return txsel . localAccountsDB . GetIdxByEthAddrBJJ ( txsel . coordAccount . Addr , txsel . coordAccount . BJJ , tokenID )
return txsel . localAccountsDB . GetIdxByEthAddrBJJ ( txsel . coordAccount . Addr ,
txsel . coordAccount . BJJ , tokenID )
}
// coordAccountForTokenID creates a new L1CoordinatorTx to create a new
@ -108,8 +100,8 @@ func (txsel *TxSelector) getCoordIdx(tokenID common.TokenID) (common.Idx, error)
// not exist yet in the db, and does not exist a L1CoordinatorTx to creat that
// account in the given array of L1CoordinatorTxs. If a new Coordinator account
// needs to be created, a new L1CoordinatorTx will be returned from this
// function.
//nolint:unused
// function. After calling this method, if the l1CoordinatorTx is added to the
// selection, positionL1 must be increased 1.
func ( txsel * TxSelector ) coordAccountForTokenID ( l1CoordinatorTxs [ ] common . L1Tx ,
tokenID common . TokenID , positionL1 int ) ( * common . L1Tx , int , error ) {
// check if CoordinatorAccount for TokenID is already pending to create
@ -117,7 +109,7 @@ func (txsel *TxSelector) coordAccountForTokenID(l1CoordinatorTxs []common.L1Tx,
txsel . coordAccount . Addr , txsel . coordAccount . BJJ ) {
return nil , positionL1 , nil
}
_ , err := txsel . localAccountsDB . GetIdxByEthAddrBJJ ( txsel . coordAccount . Addr , txsel . coordAccount . BJJ , tokenID )
_ , err := txsel . getCoordIdx ( tokenID )
if tracerr . Unwrap ( err ) == statedb . ErrIdxNotFound {
// create L1CoordinatorTx to create new CoordAccount for
// TokenID
@ -131,7 +123,6 @@ func (txsel *TxSelector) coordAccountForTokenID(l1CoordinatorTxs []common.L1Tx,
DepositAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeCreateAccountDeposit ,
}
positionL1 ++
return & l1CoordinatorTx , positionL1 , nil
}
@ -152,7 +143,8 @@ func (txsel *TxSelector) coordAccountForTokenID(l1CoordinatorTxs []common.L1Tx,
// creation exists. The L1UserTxs, L1CoordinatorTxs, PoolL2Txs that will be
// included in the next batch.
func ( txsel * TxSelector ) GetL2TxSelection ( selectionConfig * SelectionConfig ,
batchNum common . BatchNum ) ( [ ] common . Idx , [ ] [ ] byte , [ ] common . L1Tx , [ ] common . PoolL2Tx , error ) {
batchNum common . BatchNum ) ( [ ] common . Idx , [ ] [ ] byte , [ ] common . L1Tx ,
[ ] common . PoolL2Tx , error ) {
coordIdxs , accCreationAuths , _ , l1CoordinatorTxs , l2Txs , err :=
txsel . GetL1L2TxSelection ( selectionConfig , batchNum , [ ] common . L1Tx { } )
return coordIdxs , accCreationAuths , l1CoordinatorTxs , l2Txs , tracerr . Wrap ( err )
@ -167,12 +159,18 @@ func (txsel *TxSelector) GetL2TxSelection(selectionConfig *SelectionConfig,
// creation exists. The L1UserTxs, L1CoordinatorTxs, PoolL2Txs that will be
// included in the next batch.
func ( txsel * TxSelector ) GetL1L2TxSelection ( selectionConfig * SelectionConfig ,
batchNum common . BatchNum , l1Txs [ ] common . L1Tx ) ( [ ] common . Idx , [ ] [ ] byte , [ ] common . L1Tx ,
[ ] common . L1Tx , [ ] common . PoolL2Tx , error ) {
// TODO WIP this method uses a 'cherry-pick' of internal calls of the
batchNum common . BatchNum , l1UserTxs [ ] common . L1Tx ) ( [ ] common . Idx , [ ] [ ] byte ,
[ ] common . L1Tx , [ ] common . L1Tx , [ ] common . PoolL2Tx , error ) {
// TODO input parameter 'batchNum' is not used, delete
// WIP.0: the TxSelector is not optimized and will need a redesign. The
// current version is implemented in order to have a functional
// implementation that can be used asap.
//
// WIP.1: this method uses a 'cherry-pick' of internal calls of the
// StateDB, a refactor of the StateDB to reorganize it internally is
// planned once the main functionallities are covered, with that
// refactor the TxSelector will be updated also
// refactor the TxSelector will be updated also.
// get pending l2-tx from tx-pool
l2TxsRaw , err := txsel . l2db . GetPendingTxs ( )
@ -184,59 +182,77 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
tp := txprocessor . NewTxProcessor ( txselStateDB , selectionConfig . TxProcessorConfig )
// Process L1UserTxs
for i := 0 ; i < len ( l1Txs ) ; i ++ {
for i := 0 ; i < len ( l1User Txs ) ; i ++ {
// assumption: l1usertx are sorted by L1Tx.Position
_ , _ , _ , _ , err := tp . ProcessL1Tx ( nil , & l1Txs [ i ] )
_ , _ , _ , _ , err := tp . ProcessL1Tx ( nil , & l1User Txs [ i ] )
if err != nil {
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
}
var l1CoordinatorTxs [ ] common . L1Tx
positionL1 := len ( l1Txs )
positionL1 := len ( l1User Txs )
var accAuths [ ] [ ] byte
// sort l2TxsRaw (cropping at MaxTx at this point)
l2Txs := txsel . getL2Profitable ( l2TxsRaw , selectionConfig . TxProcessorConfig . MaxTx )
// TODO for L1CoordinatorTxs check that always len(l1UserTxs)+len(l1CoordinatorTxs)<MaxL1Txs
l2Txs0 := txsel . getL2Profitable ( l2TxsRaw , selectionConfig . TxProcessorConfig . MaxTx )
noncesMap := make ( map [ common . Idx ] common . Nonce )
var l2Txs [ ] common . PoolL2Tx
// iterate over l2Txs
// - if tx.TokenID does not exist at CoordsIdxDB
// - create new L1CoordinatorTx, for Coordinator to receive the fee of the new TokenID
for i := 0 ; i < len ( l2Txs ) ; i ++ {
// check if l2Tx.TokenID does not exist at CoordsIdxDB
_ , err = txsel . getCoordIdx ( l2Txs [ i ] . TokenID ) // TODO already used inside coordAccountForTokenID, this will be removed
if tracerr . Unwrap ( err ) != db . ErrNotFound {
// if TokenID does not exist yet, create new
// L1CoordinatorTx to create the CoordinatorAccount for
// that TokenID, to receive the fees. Only in the case
// that there does not exist yet a pending
// L1CoordinatorTx to create the account for the
// Coordinator for that TokenID
// TODO TMP
// var newL1CoordTx *common.L1Tx
// newL1CoordTx, positionL1, err =
// txsel.coordAccountForTokenID(l1CoordinatorTxs,
// l2TxsRaw[i].TokenID, positionL1)
// if err != nil {
// return nil, nil, nil, nil, nil, tracerr.Wrap(err)
// }
// if newL1CoordTx != nil {
// l1CoordinatorTxs = append(l1CoordinatorTxs, *newL1CoordTx)
// }
} else if err != nil {
// - create new L1CoordinatorTx creating a CoordAccount, for
// Coordinator to receive the fee of the new TokenID
for i := 0 ; i < len ( l2Txs0 ) ; i ++ {
accSender , err := tp . StateDB ( ) . GetAccount ( l2Txs0 [ i ] . FromIdx )
if err != nil {
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
// populate the noncesMap used at the next iteration
noncesMap [ l2Txs0 [ i ] . FromIdx ] = accSender . Nonce
// if TokenID does not exist yet, create new L1CoordinatorTx to
// create the CoordinatorAccount for that TokenID, to receive
// the fees. Only in the case that there does not exist yet a
// pending L1CoordinatorTx to create the account for the
// Coordinator for that TokenID
var newL1CoordTx * common . L1Tx
newL1CoordTx , positionL1 , err =
txsel . coordAccountForTokenID ( l1CoordinatorTxs ,
accSender . TokenID , positionL1 )
if err != nil {
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
if newL1CoordTx != nil {
// if there is no space for the L1CoordinatorTx, discard the L2Tx
if len ( l1CoordinatorTxs ) >= int ( selectionConfig . MaxL1UserTxs ) - len ( l1UserTxs ) {
// discard L2Tx
continue
}
// increase positionL1
positionL1 ++
l1CoordinatorTxs = append ( l1CoordinatorTxs , * newL1CoordTx )
accAuths = append ( accAuths , txsel . coordAccount . AccountCreationAuth )
}
l2Txs = append ( l2Txs , l2Txs0 [ i ] )
}
var validTxs txs
var validTxs [ ] common . PoolL2Tx
// iterate over l2TxsRaw
// - check Nonces
// - if needed, create new L1CoordinatorTxs for unexisting ToIdx
// - keep used accAuths
// - put the valid txs into validTxs array
for i := 0 ; i < len ( l2Txs ) ; i ++ {
// check if Nonce is correct
nonce := noncesMap [ l2Txs [ i ] . FromIdx ]
if l2Txs [ i ] . Nonce == nonce {
noncesMap [ l2Txs [ i ] . FromIdx ] ++
} else {
// not valid Nonce at tx
continue
}
// If tx.ToIdx>=256, tx.ToIdx should exist to localAccountsDB,
// if so, tx is used. If tx.ToIdx==0, for an L2Tx will be the
// case of TxToEthAddr or TxToBJJ, check if
@ -246,16 +262,20 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
// of CreateAccountAndDeposit is created. If tx.ToIdx==1, is a
// Exit type and is used.
if l2Txs [ i ] . ToIdx == 0 { // ToEthAddr/ToBJJ case
var accAuth * common . AccountCreationAuth
validTxs , l1CoordinatorTxs , accAuth , positionL1 , err =
txsel . processTxToEthAddrBJJ ( validTxs , l1CoordinatorTxs ,
positionL1 , l2Txs [ i ] )
validL2Tx , l1CoordinatorTx , accAuth , err :=
txsel . processTxToEthAddrBJJ ( validTxs , selectionConfig ,
len ( l1UserTxs ) , l1CoordinatorTxs , positionL1 , l2Txs [ i ] )
if err != nil {
log . Debug ( err )
continue
}
if accAuth != nil {
if accAuth != nil && l1CoordinatorTx != nil {
accAuths = append ( accAuths , accAuth . Signature )
l1CoordinatorTxs = append ( l1CoordinatorTxs , * l1CoordinatorTx )
positionL1 ++
}
if validL2Tx != nil {
validTxs = append ( validTxs , * validL2Tx )
}
} else if l2Txs [ i ] . ToIdx >= common . IdxUserThreshold {
_ , err = txsel . localAccountsDB . GetAccount ( l2Txs [ i ] . ToIdx )
@ -285,17 +305,23 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
// get CoordIdxsMap for the TokenIDs
coordIdxsMap := make ( map [ common . TokenID ] common . Idx )
// TODO TMP (related to L#260
// for i := 0; i < len(l2Txs); i++ {
// coordIdx, err := txsel.getCoordIdx(l2Txs[i].TokenID)
// if err != nil {
// // if err is db.ErrNotFound, should not happen, as all
// // the l2Txs.TokenID should have a CoordinatorIdx
// // created in the DB at this point
// return nil, nil, nil, nil, nil, tracerr.Wrap(err)
// }
// coordIdxsMap[l2Txs[i].TokenID] = coordIdx
// }
for i := 0 ; i < len ( l2Txs ) ; i ++ {
// get TokenID from tx.Sender
accSender , err := tp . StateDB ( ) . GetAccount ( l2Txs [ i ] . FromIdx )
if err != nil {
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
tokenID := accSender . TokenID
coordIdx , err := txsel . getCoordIdx ( tokenID )
if err != nil {
// if err is db.ErrNotFound, should not happen, as all
// the l2Txs.TokenID should have a CoordinatorIdx
// created in the DB at this point
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
coordIdxsMap [ tokenID ] = coordIdx
}
var coordIdxs [ ] common . Idx
tp . AccumulatedFees = make ( map [ common . Idx ] * big . Int )
@ -303,10 +329,16 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
tp . AccumulatedFees [ idx ] = big . NewInt ( 0 )
coordIdxs = append ( coordIdxs , idx )
}
// sort CoordIdxs
sort . SliceStable ( coordIdxs , func ( i , j int ) bool {
return coordIdxs [ i ] < coordIdxs [ j ]
} )
// get most profitable L2-tx
maxL2Txs := selectionConfig . TxProcessorConfig . MaxTx - uint32 ( len ( l1CoordinatorTxs ) ) // - len(l1UserTxs) // TODO if there are L1UserTxs take them in to account
selectedL2Txs := txsel . getL2Profitable ( l2Txs , maxL2Txs ) // TODO this will only need to crop the lasts, as are already sorted
maxL2Txs := selectionConfig . TxProcessorConfig . MaxTx -
uint32 ( len ( l1UserTxs ) ) - uint32 ( len ( l1CoordinatorTxs ) )
selectedL2Txs := txsel . getL2Profitable ( l2Txs , maxL2Txs ) // TODO this will only need to crop the lasts, as are already sorted
for i := 0 ; i < len ( selectedL2Txs ) ; i ++ {
_ , _ , _ , err = tp . ProcessL2Tx ( coordIdxsMap , nil , nil , & selectedL2Txs [ i ] )
if err != nil {
@ -314,7 +346,32 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
}
}
return coordIdxs , accAuths , l1Txs , l1CoordinatorTxs , selectedL2Txs , nil
// distribute the AccumulatedFees from the processed L2Txs into the
// Coordinator Idxs
for idx , accumulatedFee := range tp . AccumulatedFees {
cmp := accumulatedFee . Cmp ( big . NewInt ( 0 ) )
if cmp == 1 { // accumulatedFee>0
// send the fee to the Idx of the Coordinator for the TokenID
accCoord , err := txsel . localAccountsDB . GetAccount ( idx )
if err != nil {
log . Errorw ( "Can not distribute accumulated fees to coordinator account: No coord Idx to receive fee" , "idx" , idx )
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
accCoord . Balance = new ( big . Int ) . Add ( accCoord . Balance , accumulatedFee )
_ , err = txsel . localAccountsDB . UpdateAccount ( idx , accCoord )
if err != nil {
log . Error ( err )
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
}
}
err = tp . StateDB ( ) . MakeCheckpoint ( )
if err != nil {
return nil , nil , nil , nil , nil , tracerr . Wrap ( err )
}
return coordIdxs , accAuths , l1UserTxs , l1CoordinatorTxs , selectedL2Txs , nil
}
// processTxsToEthAddrBJJ process the common.PoolL2Tx in the case where
@ -323,18 +380,26 @@ func (txsel *TxSelector) GetL1L2TxSelection(selectionConfig *SelectionConfig,
// CreateAccountDeposit (with 0 as DepositAmount) is created and added to the
// l1CoordinatorTxs array, and then the PoolL2Tx is added into the validTxs
// array.
func ( txsel * TxSelector ) processTxToEthAddrBJJ ( validTxs txs , l1CoordinatorTxs [ ] common . L1Tx ,
positionL1 int , l2Tx common . PoolL2Tx ) ( txs , [ ] common . L1Tx , * common . AccountCreationAuth , int , error ) {
func ( txsel * TxSelector ) processTxToEthAddrBJJ ( validTxs [ ] common . PoolL2Tx ,
selectionConfig * SelectionConfig , nL1UserTxs int , l1CoordinatorTxs [ ] common . L1Tx ,
positionL1 int , l2Tx common . PoolL2Tx ) ( * common . PoolL2Tx , * common . L1Tx ,
* common . AccountCreationAuth , error ) {
accSender , err := txsel . localAccountsDB . GetAccount ( l2Tx . FromIdx )
if err != nil {
return nil , nil , nil , err
}
l2Tx . TokenID = accSender . TokenID // TODO rm and add it before at GetL1L2TxsSelection
// if L2Tx needs a new L1CoordinatorTx of CreateAccount type, and a
// previous L2Tx in the current process already created a
// L1CoordinatorTx of this type, in the DB there still seem that needs
// to create a new L1CoordinatorTx, but as is already created, the tx
// is valid
if checkAlreadyPendingToCreate ( l1CoordinatorTxs , l2Tx . TokenID , l2Tx . ToEthAddr , l2Tx . ToBJJ ) {
validTxs = append ( validTxs , l2Tx )
return validTxs , l1CoordinatorTxs , nil , positionL1 , nil
return & l2Tx , nil , nil , nil
}
var l1CoordinatorTx * common . L1Tx
var accAuth * common . AccountCreationAuth
if ! bytes . Equal ( l2Tx . ToEthAddr . Bytes ( ) , common . EmptyAddr . Bytes ( ) ) &&
! bytes . Equal ( l2Tx . ToEthAddr . Bytes ( ) , common . FFAddr . Bytes ( ) ) {
@ -348,24 +413,22 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs txs, l1CoordinatorTxs []
// account for ToEthAddr&ToBJJ already exist,
// there is no need to create a new one.
// tx valid, StateDB will use the ToIdx==0 to define the AuxToIdx
validTxs = append ( validTxs , l2Tx )
return validTxs , l1CoordinatorTxs , nil , positionL1 , nil
return & l2Tx , nil , nil , nil
}
// if not, check if AccountCreationAuth exist for that
// ToEthAddr
accAuth , err = txsel . l2db . GetAccountCreationAuth ( l2Tx . ToEthAddr )
if err != nil {
// not found, l2Tx will not be added in the selection
return validTxs , l1CoordinatorTxs , nil , positionL1 , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s" ,
return nil , nil , nil , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s" ,
l2Tx . ToIdx , l2Tx . ToEthAddr . Hex ( ) ) )
}
if accAuth . BJJ != l2Tx . ToBJJ {
// if AccountCreationAuth.BJJ is not the same
// than in the tx, tx is not accepted
return validTxs , l1CoordinatorTxs , nil , positionL1 , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr & ToBJJ found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s, ToBJJ: %s" ,
return nil , nil , nil , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr & ToBJJ found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s, ToBJJ: %s" ,
l2Tx . ToIdx , l2Tx . ToEthAddr . Hex ( ) , l2Tx . ToBJJ . String ( ) ) )
}
validTxs = append ( validTxs , l2Tx )
} else {
// case: ToBJJ==0:
// if idx exist for EthAddr use it
@ -374,20 +437,18 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs txs, l1CoordinatorTxs []
// account for ToEthAddr already exist,
// there is no need to create a new one.
// tx valid, StateDB will use the ToIdx==0 to define the AuxToIdx
validTxs = append ( validTxs , l2Tx )
return validTxs , l1CoordinatorTxs , nil , positionL1 , nil
return & l2Tx , nil , nil , nil
}
// if not, check if AccountCreationAuth exist for that ToEthAddr
accAuth , err = txsel . l2db . GetAccountCreationAuth ( l2Tx . ToEthAddr )
if err != nil {
// not found, l2Tx will not be added in the selection
return validTxs , l1CoordinatorTxs , nil , positionL1 , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s" ,
return nil , nil , nil , tracerr . Wrap ( fmt . Errorf ( "invalid L2Tx: ToIdx not found in StateDB, neither ToEthAddr found in AccountCreationAuths L2DB. ToIdx: %d, ToEthAddr: %s" ,
l2Tx . ToIdx , l2Tx . ToEthAddr ) )
}
validTxs = append ( validTxs , l2Tx )
}
// create L1CoordinatorTx for the accountCreation
l1CoordinatorTx := common . L1Tx {
l1CoordinatorTx = & common . L1Tx {
Position : positionL1 ,
UserOrigin : false ,
FromEthAddr : accAuth . EthAddr ,
@ -397,9 +458,8 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs txs, l1CoordinatorTxs []
DepositAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeCreateAccountDeposit ,
}
positionL1 ++
l1CoordinatorTxs = append ( l1CoordinatorTxs , l1CoordinatorTx )
} else if bytes . Equal ( l2Tx . ToEthAddr . Bytes ( ) , common . FFAddr . Bytes ( ) ) && l2Tx . ToBJJ != common . EmptyBJJComp {
} else if bytes . Equal ( l2Tx . ToEthAddr . Bytes ( ) , common . FFAddr . Bytes ( ) ) &&
l2Tx . ToBJJ != common . EmptyBJJComp {
// if idx exist for EthAddr&BJJ use it
_ , err := txsel . localAccountsDB . GetIdxByEthAddrBJJ ( l2Tx . ToEthAddr , l2Tx . ToBJJ ,
l2Tx . TokenID )
@ -407,14 +467,12 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs txs, l1CoordinatorTxs []
// account for ToEthAddr&ToBJJ already exist, (where ToEthAddr==0xff)
// there is no need to create a new one.
// tx valid, StateDB will use the ToIdx==0 to define the AuxToIdx
validTxs = append ( validTxs , l2Tx )
return validTxs , l1CoordinatorTxs , nil , positionL1 , nil
return & l2Tx , nil , nil , nil
}
// if idx don't exist for EthAddr&BJJ,
// coordinator can create a new account without
// L1Authorization, as ToEthAddr==0xff
// if idx don't exist for EthAddr&BJJ, coordinator can create a
// new account without L1Authorization, as ToEthAddr==0xff
// create L1CoordinatorTx for the accountCreation
l1CoordinatorTx := common . L1Tx {
l1CoordinatorTx = & common . L1Tx {
Position : positionL1 ,
UserOrigin : false ,
FromEthAddr : l2Tx . ToEthAddr ,
@ -424,11 +482,13 @@ func (txsel *TxSelector) processTxToEthAddrBJJ(validTxs txs, l1CoordinatorTxs []
DepositAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeCreateAccountDeposit ,
}
positionL1 ++
l1CoordinatorTxs = append ( l1CoordinatorTxs , l1CoordinatorTx )
}
if len ( l1CoordinatorTxs ) >= int ( selectionConfig . MaxL1UserTxs ) - nL1UserTxs {
// L2Tx discarded
return nil , nil , nil , tracerr . Wrap ( fmt . Errorf ( "L2Tx discarded due not slots for L1CoordinatorTx to create a new account for receiver of L2Tx" ) )
}
return validTxs , l1CoordinatorTxs , accAuth , positionL1 , nil
return & l2Tx , l1CoordinatorTx , accAuth , nil
}
func checkAlreadyPendingToCreate ( l1CoordinatorTxs [ ] common . L1Tx , tokenID common . TokenID ,
@ -444,21 +504,21 @@ func checkAlreadyPendingToCreate(l1CoordinatorTxs []common.L1Tx, tokenID common.
}
// getL2Profitable returns the profitable selection of L2Txssorted by Nonce
func ( txsel * TxSelector ) getL2Profitable ( txs txs , max uint32 ) txs {
sort . Sort ( txs )
if len ( t xs) < int ( max ) {
return t xs
func ( txsel * TxSelector ) getL2Profitable ( l2Txs [ ] common . PoolL2Tx , max uint32 ) [ ] common . PoolL2Tx {
sort . Sort ( txs ( l2Txs ) )
if len ( l2T xs) < int ( max ) {
return l2T xs
}
txs = t xs[ : max ]
l2Txs = l2T xs[ : max ]
// sort l2Txs by Nonce. This can be done in many different ways, what
// is needed is to output the txs where the Nonce of t xs for each
// Account is sorted, but the t xs can not be grouped by sender Account
// is needed is to output the l2Txs where the Nonce of l2T xs for each
// Account is sorted, but the l2T xs can not be grouped by sender Account
// neither by Fee. This is because later on the Nonces will need to be
// sequential for the zkproof generation.
sort . SliceStable ( t xs, func ( i , j int ) bool {
return t xs[ i ] . Nonce < t xs[ j ] . Nonce
sort . SliceStable ( l2T xs, func ( i , j int ) bool {
return l2T xs[ i ] . Nonce < l2T xs[ j ] . Nonce
} )
return t xs
return l2T xs
}