Browse Source

Move logic to extend til blocks to til

Previously, the synchronizer test was extending the output from til to
precalculate many fields to compare it with the synchronizer and BD output.
Since this is useful outside of the syncrhonizer testing: move this
functionality to til via a function that extends the output
(til.Context.FillBlocksExtra).

Also, add new functionality: calculate fee idxs dynamically by setting a user
name, and calculate collected fees.
feature/sql-semaphore1
Eduard S 4 years ago
parent
commit
5ebf46e045
6 changed files with 282 additions and 154 deletions
  1. +12
    -11
      common/batch.go
  2. +1
    -1
      db/historydb/historydb.go
  3. +1
    -0
      db/migrations/0001.sql
  4. +14
    -9
      synchronizer/synchronizer.go
  5. +15
    -126
      synchronizer/synchronizer_test.go
  6. +239
    -7
      test/til/txs.go

+ 12
- 11
common/batch.go

@ -12,17 +12,18 @@ const batchNumBytesLen = 8
// Batch is a struct that represents Hermez network batch
type Batch struct {
BatchNum BatchNum `meddler:"batch_num"`
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum block in which the batch is forged
ForgerAddr ethCommon.Address `meddler:"forger_addr"`
CollectedFees map[TokenID]*big.Int `meddler:"fees_collected,json"`
StateRoot *big.Int `meddler:"state_root,bigint"`
NumAccounts int `meddler:"num_accounts"`
LastIdx int64 `meddler:"last_idx"`
ExitRoot *big.Int `meddler:"exit_root,bigint"`
ForgeL1TxsNum *int64 `meddler:"forge_l1_txs_num"` // optional, Only when the batch forges L1 txs. Identifier that corresponds to the group of L1 txs forged in the current batch.
SlotNum int64 `meddler:"slot_num"` // Slot in which the batch is forged
TotalFeesUSD *float64 `meddler:"total_fees_usd"`
BatchNum BatchNum `meddler:"batch_num"`
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum block in which the batch is forged
ForgerAddr ethCommon.Address `meddler:"forger_addr"`
CollectedFees map[TokenID]*big.Int `meddler:"fees_collected,json"`
FeeIdxsCoordinator []Idx `meddler:"fee_idxs_coordinator,json"`
StateRoot *big.Int `meddler:"state_root,bigint"`
NumAccounts int `meddler:"num_accounts"`
LastIdx int64 `meddler:"last_idx"`
ExitRoot *big.Int `meddler:"exit_root,bigint"`
ForgeL1TxsNum *int64 `meddler:"forge_l1_txs_num"` // optional, Only when the batch forges L1 txs. Identifier that corresponds to the group of L1 txs forged in the current batch.
SlotNum int64 `meddler:"slot_num"` // Slot in which the batch is forged
TotalFeesUSD *float64 `meddler:"total_fees_usd"`
}
// BatchNum identifies a batch

+ 1
- 1
db/historydb/historydb.go

@ -279,7 +279,7 @@ func (hdb *HistoryDB) GetAllBatches() ([]common.Batch, error) {
err := meddler.QueryAll(
hdb.db, &batches,
`SELECT batch.batch_num, batch.eth_block_num, batch.forger_addr, batch.fees_collected,
batch.state_root, batch.num_accounts, batch.last_idx, batch.exit_root,
batch.fee_idxs_coordinator, batch.state_root, batch.num_accounts, batch.last_idx, batch.exit_root,
batch.forge_l1_txs_num, batch.slot_num, batch.total_fees_usd FROM batch;`,
)
return db.SlicePtrsToSlice(batches).([]common.Batch), err

+ 1
- 0
db/migrations/0001.sql

@ -21,6 +21,7 @@ CREATE TABLE batch (
eth_block_num BIGINT NOT NULL REFERENCES block (eth_block_num) ON DELETE CASCADE,
forger_addr BYTEA NOT NULL, -- fake foreign key for coordinator
fees_collected BYTEA NOT NULL,
fee_idxs_coordinator BYTEA NOT NULL,
state_root BYTEA NOT NULL,
num_accounts BIGINT NOT NULL,
last_idx BIGINT NOT NULL,

+ 14
- 9
synchronizer/synchronizer.go

@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/hermeznetwork/hermez-node/common"
@ -467,6 +468,8 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e
for i := range processTxsOut.CreatedAccounts {
createdAccount := &processTxsOut.CreatedAccounts[i]
createdAccount.Nonce = 0
createdAccount.Balance = big.NewInt(0)
createdAccount.BatchNum = batchNum
}
batchData.CreatedAccounts = processTxsOut.CreatedAccounts
@ -478,16 +481,18 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e
}
// Get Batch information
// fmt.Printf("DBG: %#v\n", forgeBatchArgs.FeeIdxCoordinator)
batch := common.Batch{
BatchNum: batchNum,
EthBlockNum: blockNum,
ForgerAddr: *sender,
CollectedFees: processTxsOut.CollectedFees,
StateRoot: forgeBatchArgs.NewStRoot,
NumAccounts: len(batchData.CreatedAccounts),
LastIdx: forgeBatchArgs.NewLastIdx,
ExitRoot: forgeBatchArgs.NewExitRoot,
SlotNum: slotNum,
BatchNum: batchNum,
EthBlockNum: blockNum,
ForgerAddr: *sender,
CollectedFees: processTxsOut.CollectedFees,
FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
StateRoot: forgeBatchArgs.NewStRoot,
NumAccounts: len(batchData.CreatedAccounts),
LastIdx: forgeBatchArgs.NewLastIdx,
ExitRoot: forgeBatchArgs.NewExitRoot,
SlotNum: slotNum,
}
nextForgeL1TxsNumCpy := nextForgeL1TxsNum
if forgeBatchArgs.L1Batch {

+ 15
- 126
synchronizer/synchronizer_test.go

@ -23,8 +23,6 @@ import (
)
var tokenConsts = map[common.TokenID]eth.ERC20Consts{}
var forceExits = map[int64][]common.ExitInfo{} // ForgeL1TxsNum -> []exit
var nonces = map[common.Idx]common.Nonce{}
type timer struct {
time int64
@ -103,10 +101,8 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
dbL1CoordinatorTxs, err := s.historyDB.GetAllL1CoordinatorTxs()
require.Nil(t, err)
// fmt.Printf("DBG dbL1CoordinatorTxs: %+v\n", dbL1CoordinatorTxs)
dbL2Txs, err := s.historyDB.GetAllL2Txs()
require.Nil(t, err)
// fmt.Printf("DBG dbL2Txs: %+v\n", dbL2Txs)
dbExits, err := s.historyDB.GetAllExits()
require.Nil(t, err)
// dbL1CoordinatorTxs := []common.L1Tx{}
@ -125,7 +121,7 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
// We don't care about TotalFeesUSD. Use the syncBatch that
// has a TotalFeesUSD inserted by the HistoryDB
batch.Batch.TotalFeesUSD = syncBatch.Batch.TotalFeesUSD
batch.CreatedAccounts = syncBatch.CreatedAccounts // til doesn't output CreatedAccounts
assert.Equal(t, batch.CreatedAccounts, syncBatch.CreatedAccounts)
batch.Batch.NumAccounts = len(batch.CreatedAccounts)
// Test field by field to facilitate debugging of errors
@ -139,12 +135,6 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
assert.Equal(t, exit.Balance, syncBatch.ExitTree[j].Balance)
*exit = syncBatch.ExitTree[j]
}
// We are collecting fees after blockNum=2 in 2 idxs
if block.Block.EthBlockNum > 2 {
// fmt.Printf("DBG collectedFees: %+v\n", syncBatch.Batch.CollectedFees)
assert.Equal(t, 2, len(syncBatch.Batch.CollectedFees))
}
batch.Batch.CollectedFees = syncBatch.Batch.CollectedFees
assert.Equal(t, batch.Batch, syncBatch.Batch)
assert.Equal(t, batch, syncBatch)
assert.Equal(t, &batch.Batch, dbBatch) //nolint:gosec
@ -305,9 +295,12 @@ func TestSync(t *testing.T) {
> batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{2}
> batchL1 // forge L1UserTxs{2}, freeze defined L1UserTxs{nil}
> block // blockNum=3
`
tc := til.NewContext(common.RollupConstMaxL1UserTx)
tilCfgExtra := til.ConfigExtra{
BootCoordAddr: bootCoordAddr,
CoordUser: "A",
}
blocks, err := tc.GenerateBlocks(set1)
require.Nil(t, err)
// Sanity check
@ -339,6 +332,9 @@ func TestSync(t *testing.T) {
}
}
err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
assert.Nil(t, err)
// Add block data to the smart contracts
for _, block := range blocks {
for _, token := range block.Rollup.AddedTokens {
@ -352,12 +348,12 @@ func TestSync(t *testing.T) {
require.Nil(t, err)
}
client.CtlSetAddr(bootCoordAddr)
feeIdxCoordinator := []common.Idx{}
if block.Block.EthBlockNum > 2 {
// After blockNum=2 we have some accounts, use them as
// coordinator owned to receive fees.
feeIdxCoordinator = []common.Idx{common.Idx(256), common.Idx(259)}
}
// feeIdxCoordinator := []common.Idx{}
// if block.Block.EthBlockNum > 2 {
// // After blockNum=2 we have some accounts, use them as
// // coordinator owned to receive fees.
// feeIdxCoordinator = []common.Idx{common.Idx(256), common.Idx(259)}
// }
for _, batch := range block.Rollup.Batches {
_, err := client.RollupForgeBatch(&eth.RollupForgeBatchArgs{
NewLastIdx: batch.Batch.LastIdx,
@ -366,7 +362,7 @@ func TestSync(t *testing.T) {
L1CoordinatorTxs: batch.L1CoordinatorTxs,
L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty
L2TxsData: batch.L2Txs,
FeeIdxCoordinator: feeIdxCoordinator,
FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator,
// Circuit selector
VerifierIdx: 0, // Intentionally empty
L1Batch: batch.L1Batch,
@ -380,113 +376,6 @@ func TestSync(t *testing.T) {
client.CtlMineBlock()
}
// Fill extra fields not generated by til in til block
openToForge := int64(0)
toForgeL1TxsNum := int64(0)
l1UserTxsLen := map[int64]int{} // ForgeL1TxsNum -> len(L1UserTxs)
for i := range blocks {
block := &blocks[i]
// Count number of L1UserTxs in each queue, to figure out later
// position of L1CoordinatorTxs and L2Txs
for j := range block.Rollup.L1UserTxs {
tx := &block.Rollup.L1UserTxs[j]
l1UserTxsLen[*tx.ToForgeL1TxsNum]++
if tx.Type == common.TxTypeForceExit {
forceExits[*tx.ToForgeL1TxsNum] = append(forceExits[*tx.ToForgeL1TxsNum],
common.ExitInfo{
AccountIdx: tx.FromIdx,
Balance: tx.Amount,
})
}
}
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
if batch.L1Batch {
// Set BatchNum for forged L1UserTxs to til blocks
bn := batch.Batch.BatchNum
for k := range blocks {
block := &blocks[k]
for l := range block.Rollup.L1UserTxs {
tx := &block.Rollup.L1UserTxs[l]
if *tx.ToForgeL1TxsNum == openToForge {
tx.BatchNum = &bn
}
}
}
openToForge++
}
batch.Batch.EthBlockNum = block.Block.EthBlockNum
batch.Batch.ForgerAddr = bootCoordAddr // til doesn't fill the batch forger addr
if batch.L1Batch {
toForgeL1TxsNumCpy := toForgeL1TxsNum
batch.Batch.ForgeL1TxsNum = &toForgeL1TxsNumCpy // til doesn't fill the ForgeL1TxsNum
toForgeL1TxsNum++
}
batchNum := batch.Batch.BatchNum
for k := range batch.L1CoordinatorTxs {
tx := &batch.L1CoordinatorTxs[k]
tx.BatchNum = &batchNum
tx.EthBlockNum = batch.Batch.EthBlockNum
}
}
}
// Fill expected positions in L1CoordinatorTxs and L2Txs
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
position := 0
if batch.L1Batch {
position = l1UserTxsLen[*batch.Batch.ForgeL1TxsNum]
}
for k := range batch.L1CoordinatorTxs {
tx := &batch.L1CoordinatorTxs[k]
tx.Position = position
position++
nTx, err := common.NewL1Tx(tx)
require.Nil(t, err)
*tx = *nTx
}
for k := range batch.L2Txs {
tx := &batch.L2Txs[k]
tx.Position = position
position++
nonces[tx.FromIdx]++
tx.Nonce = nonces[tx.FromIdx]
nTx, err := common.NewL2Tx(tx)
require.Nil(t, err)
*tx = *nTx
}
}
}
// Fill ExitTree (only AccountIdx and Balance)
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
if batch.L1Batch {
for forgeL1TxsNum, exits := range forceExits {
if forgeL1TxsNum == *batch.Batch.ForgeL1TxsNum {
batch.ExitTree = append(batch.ExitTree, exits...)
}
}
}
for k := range batch.L2Txs {
tx := &batch.L2Txs[k]
if tx.Type == common.TxTypeExit {
batch.ExitTree = append(batch.ExitTree, common.ExitInfo{
AccountIdx: tx.FromIdx,
Balance: tx.Amount,
})
}
}
}
}
//
// Sync to synchronize the current state from the test smart contracts,
// and check the outcome

+ 239
- 7
test/til/txs.go

@ -21,7 +21,10 @@ func newBatchData(batchNum int) common.BatchData {
L2Txs: []common.L2Tx{},
Batch: common.Batch{
BatchNum: common.BatchNum(batchNum),
StateRoot: big.NewInt(0), ExitRoot: big.NewInt(0)},
StateRoot: big.NewInt(0), ExitRoot: big.NewInt(0),
FeeIdxsCoordinator: make([]common.Idx, 0),
CollectedFees: make(map[common.TokenID]*big.Int),
},
}
}
@ -36,13 +39,22 @@ func newBlock(blockNum int64) common.BlockData {
}
}
type contextExtra struct {
openToForge int64
toForgeL1TxsNum int64
nonces map[common.Idx]common.Nonce
idx int
}
// Context contains the data of the test
type Context struct {
Instructions []instruction
userNames []string
Users map[string]*User
Users map[string]*User // Name -> *User
usersByIdx map[int]*User
accountsByIdx map[int]*Account
LastRegisteredTokenID common.TokenID
l1CreatedAccounts map[string]*Account
l1CreatedAccounts map[string]*Account // (Name, TokenID) -> *Account
// rollupConstMaxL1UserTx Maximum L1-user transactions allowed to be queued in a batch
rollupConstMaxL1UserTx int
@ -59,6 +71,8 @@ type Context struct {
l2Txs []L2Tx
}
blockNum int64
extra contextExtra
}
// NewContext returns a new Context
@ -67,6 +81,8 @@ func NewContext(rollupConstMaxL1UserTx int) *Context {
return &Context{
Users: make(map[string]*User),
l1CreatedAccounts: make(map[string]*Account),
usersByIdx: make(map[int]*User),
accountsByIdx: make(map[int]*Account),
LastRegisteredTokenID: 0,
rollupConstMaxL1UserTx: rollupConstMaxL1UserTx,
@ -82,17 +98,26 @@ func NewContext(rollupConstMaxL1UserTx int) *Context {
openToForge: 1,
//nolint:gomnd
blockNum: 2, // rollup genesis blockNum
extra: contextExtra{
openToForge: 0,
toForgeL1TxsNum: 0,
nonces: make(map[common.Idx]common.Nonce),
idx: common.UserThreshold,
},
}
}
// Account contains the data related to the account for a specific TokenID of a User
type Account struct {
Idx common.Idx
Nonce common.Nonce
Idx common.Idx
TokenID common.TokenID
Nonce common.Nonce
BatchNum int
}
// User contains the data related to a testing user
type User struct {
Name string
BJJ *babyjub.PrivateKey
Addr ethCommon.Address
Accounts map[common.TokenID]*Account
@ -361,10 +386,14 @@ func (tc *Context) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error
return fmt.Errorf("Can not create same account twice (same User (%s) & same TokenID (%d)) (this is a design property of Til)", tx.fromIdxName, tx.L1Tx.TokenID)
}
tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] = &Account{
Idx: common.Idx(tc.idx),
Nonce: common.Nonce(0),
Idx: common.Idx(tc.idx),
TokenID: tx.L1Tx.TokenID,
Nonce: common.Nonce(0),
BatchNum: tc.currBatchNum,
}
tc.l1CreatedAccounts[idxTokenIDToString(tx.fromIdxName, tx.L1Tx.TokenID)] = tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID]
tc.accountsByIdx[tc.idx] = tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID]
tc.usersByIdx[tc.idx] = tc.Users[tx.fromIdxName]
tc.idx++
}
if isCoordinatorTxs {
@ -606,6 +635,7 @@ func (tc *Context) generateKeys(userNames []string) {
addr := ethCrypto.PubkeyToAddress(key.PublicKey)
u := User{
Name: userNames[i-1],
BJJ: &sk,
Addr: addr,
Accounts: make(map[common.TokenID]*Account),
@ -622,3 +652,205 @@ func L1TxsToCommonL1Txs(l1 []L1Tx) []common.L1Tx {
}
return r
}
// ConfigExtra is the configuration used in FillBlocksExtra to extend the
// blocks returned by til.
type ConfigExtra struct {
// Address to set as forger for each batch
BootCoordAddr ethCommon.Address
// Coordinator user name used to select the corresponding accounts to
// collect coordinator fees
CoordUser string
}
// FillBlocksExtra fills extra fields not generated by til in each block, so
// that the blockData is closer to what the HistoryDB stores. The filled fields are:
// - blocks[].Rollup.L1UserTxs[].BatchNum
// - blocks[].Rollup.Batch.EthBlockNum
// - blocks[].Rollup.Batch.ForgerAddr
// - blocks[].Rollup.Batch.ForgeL1TxsNum
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].TxID
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].BatchNum
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EthBlockNum
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].Position
// - blocks[].Rollup.Batch.L2Txs[].TxID
// - blocks[].Rollup.Batch.L2Txs[].Position
// - blocks[].Rollup.Batch.L2Txs[].Nonce
// - blocks[].Rollup.Batch.ExitTree
// - blocks[].Rollup.Batch.CreatedAccounts
// - blocks[].Rollup.Batch.FeeIdxCoordinator
// - blocks[].Rollup.Batch.CollectedFees
func (tc *Context) FillBlocksExtra(blocks []common.BlockData, cfg *ConfigExtra) error {
// Fill extra fields not generated by til in til block
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
if batch.L1Batch {
// Set BatchNum for forged L1UserTxs to til blocks
bn := batch.Batch.BatchNum
for k := range blocks {
block := &blocks[k]
for l := range block.Rollup.L1UserTxs {
tx := &block.Rollup.L1UserTxs[l]
if *tx.ToForgeL1TxsNum == tc.extra.openToForge {
tx.BatchNum = &bn
}
}
}
tc.extra.openToForge++
}
batch.Batch.EthBlockNum = block.Block.EthBlockNum
// til doesn't fill the batch forger addr
batch.Batch.ForgerAddr = cfg.BootCoordAddr
if batch.L1Batch {
toForgeL1TxsNumCpy := tc.extra.toForgeL1TxsNum
// til doesn't fill the ForgeL1TxsNum
batch.Batch.ForgeL1TxsNum = &toForgeL1TxsNumCpy
tc.extra.toForgeL1TxsNum++
}
batchNum := batch.Batch.BatchNum
for k := range batch.L1CoordinatorTxs {
tx := &batch.L1CoordinatorTxs[k]
tx.BatchNum = &batchNum
tx.EthBlockNum = batch.Batch.EthBlockNum
}
}
}
// Fill CreatedAccounts
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
l1Txs := []common.L1Tx{}
if batch.L1Batch {
for _, tx := range tc.Queues[*batch.Batch.ForgeL1TxsNum] {
l1Txs = append(l1Txs, tx.L1Tx)
}
}
l1Txs = append(l1Txs, batch.L1CoordinatorTxs...)
for k := range l1Txs {
tx := &l1Txs[k]
if tx.Type == common.TxTypeCreateAccountDeposit ||
tx.Type == common.TxTypeCreateAccountDepositTransfer {
user, ok := tc.usersByIdx[tc.extra.idx]
if !ok {
return fmt.Errorf("Created account with idx: %v not found", tc.extra.idx)
}
batch.CreatedAccounts = append(batch.CreatedAccounts,
common.Account{
Idx: common.Idx(tc.extra.idx),
TokenID: tx.TokenID,
BatchNum: batch.Batch.BatchNum,
PublicKey: user.BJJ.Public(),
EthAddr: user.Addr,
Nonce: 0,
Balance: big.NewInt(0),
})
tc.extra.idx++
}
}
}
}
// Fill expected positions in L1CoordinatorTxs and L2Txs
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
position := 0
if batch.L1Batch {
position = len(tc.Queues[*batch.Batch.ForgeL1TxsNum])
}
for k := range batch.L1CoordinatorTxs {
tx := &batch.L1CoordinatorTxs[k]
tx.Position = position
position++
nTx, err := common.NewL1Tx(tx)
if err != nil {
return err
}
*tx = *nTx
}
for k := range batch.L2Txs {
tx := &batch.L2Txs[k]
tx.Position = position
position++
tc.extra.nonces[tx.FromIdx]++
tx.Nonce = tc.extra.nonces[tx.FromIdx]
nTx, err := common.NewL2Tx(tx)
if err != nil {
return err
}
*tx = *nTx
}
}
}
// Fill ExitTree (only AccountIdx and Balance)
for i := range blocks {
block := &blocks[i]
for j := range block.Rollup.Batches {
batch := &block.Rollup.Batches[j]
if batch.L1Batch {
for _, _tx := range tc.Queues[*batch.Batch.ForgeL1TxsNum] {
tx := _tx.L1Tx
if tx.Type == common.TxTypeForceExit {
batch.ExitTree =
append(batch.ExitTree,
common.ExitInfo{
AccountIdx: tx.FromIdx,
Balance: tx.Amount,
})
}
}
}
for k := range batch.L2Txs {
tx := &batch.L2Txs[k]
if tx.Type == common.TxTypeExit {
batch.ExitTree = append(batch.ExitTree, common.ExitInfo{
AccountIdx: tx.FromIdx,
Balance: tx.Amount,
})
}
fee, err := common.CalcFeeAmount(tx.Amount, tx.Fee)
if err != nil {
return err
}
// Find the TokenID of the tx
fromAcc, ok := tc.accountsByIdx[int(tx.FromIdx)]
if !ok {
return fmt.Errorf("L2tx.FromIdx idx: %v not found", tx.FromIdx)
}
// Find the idx of the CoordUser for the
// TokenID, and if it exists, add the fee to
// the collectedFees. Only consider the
// coordinator account to receive fee if it was
// created in this or a previous batch
if acc, ok := tc.l1CreatedAccounts[idxTokenIDToString(cfg.CoordUser, fromAcc.TokenID)]; ok &&
common.BatchNum(acc.BatchNum) <= batch.Batch.BatchNum {
found := false
for _, idx := range batch.Batch.FeeIdxsCoordinator {
if idx == common.Idx(acc.Idx) {
found = true
break
}
}
if !found {
batch.Batch.FeeIdxsCoordinator = append(batch.Batch.FeeIdxsCoordinator,
common.Idx(acc.Idx))
batch.Batch.CollectedFees[fromAcc.TokenID] = big.NewInt(0)
}
collected := batch.Batch.CollectedFees[fromAcc.TokenID]
collected.Add(collected, fee)
}
}
}
}
return nil
}

Loading…
Cancel
Save