Browse Source

Merge pull request #261 from hermeznetwork/feature/til-extra

Move logic to extend til blocks to til
feature/sql-semaphore1
arnau 4 years ago
committed by GitHub
parent
commit
fd9b247120
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
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 // Batch is a struct that represents Hermez network batch
type Batch struct { 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 // BatchNum identifies a batch

+ 1
- 1
db/historydb/historydb.go

@ -278,7 +278,7 @@ func (hdb *HistoryDB) GetAllBatches() ([]common.Batch, error) {
err := meddler.QueryAll( err := meddler.QueryAll(
hdb.db, &batches, hdb.db, &batches,
`SELECT batch.batch_num, batch.eth_block_num, batch.forger_addr, batch.fees_collected, `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;`, batch.forge_l1_txs_num, batch.slot_num, batch.total_fees_usd FROM batch;`,
) )
return db.SlicePtrsToSlice(batches).([]common.Batch), err 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, eth_block_num BIGINT NOT NULL REFERENCES block (eth_block_num) ON DELETE CASCADE,
forger_addr BYTEA NOT NULL, -- fake foreign key for coordinator forger_addr BYTEA NOT NULL, -- fake foreign key for coordinator
fees_collected BYTEA NOT NULL, fees_collected BYTEA NOT NULL,
fee_idxs_coordinator BYTEA NOT NULL,
state_root BYTEA NOT NULL, state_root BYTEA NOT NULL,
num_accounts BIGINT NOT NULL, num_accounts BIGINT NOT NULL,
last_idx BIGINT NOT NULL, last_idx BIGINT NOT NULL,

+ 14
- 9
synchronizer/synchronizer.go

@ -4,6 +4,7 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"math/big"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/hermeznetwork/hermez-node/common" "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 { for i := range processTxsOut.CreatedAccounts {
createdAccount := &processTxsOut.CreatedAccounts[i] createdAccount := &processTxsOut.CreatedAccounts[i]
createdAccount.Nonce = 0
createdAccount.Balance = big.NewInt(0)
createdAccount.BatchNum = batchNum createdAccount.BatchNum = batchNum
} }
batchData.CreatedAccounts = processTxsOut.CreatedAccounts batchData.CreatedAccounts = processTxsOut.CreatedAccounts
@ -478,16 +481,18 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e
} }
// Get Batch information // Get Batch information
// fmt.Printf("DBG: %#v\n", forgeBatchArgs.FeeIdxCoordinator)
batch := common.Batch{ 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 nextForgeL1TxsNumCpy := nextForgeL1TxsNum
if forgeBatchArgs.L1Batch { if forgeBatchArgs.L1Batch {

+ 15
- 126
synchronizer/synchronizer_test.go

@ -23,8 +23,6 @@ import (
) )
var tokenConsts = map[common.TokenID]eth.ERC20Consts{} 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 { type timer struct {
time int64 time int64
@ -103,10 +101,8 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
dbL1CoordinatorTxs, err := s.historyDB.GetAllL1CoordinatorTxs() dbL1CoordinatorTxs, err := s.historyDB.GetAllL1CoordinatorTxs()
require.Nil(t, err) require.Nil(t, err)
// fmt.Printf("DBG dbL1CoordinatorTxs: %+v\n", dbL1CoordinatorTxs)
dbL2Txs, err := s.historyDB.GetAllL2Txs() dbL2Txs, err := s.historyDB.GetAllL2Txs()
require.Nil(t, err) require.Nil(t, err)
// fmt.Printf("DBG dbL2Txs: %+v\n", dbL2Txs)
dbExits, err := s.historyDB.GetAllExits() dbExits, err := s.historyDB.GetAllExits()
require.Nil(t, err) require.Nil(t, err)
// dbL1CoordinatorTxs := []common.L1Tx{} // 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 // We don't care about TotalFeesUSD. Use the syncBatch that
// has a TotalFeesUSD inserted by the HistoryDB // has a TotalFeesUSD inserted by the HistoryDB
batch.Batch.TotalFeesUSD = syncBatch.Batch.TotalFeesUSD 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) batch.Batch.NumAccounts = len(batch.CreatedAccounts)
// Test field by field to facilitate debugging of errors // 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) assert.Equal(t, exit.Balance, syncBatch.ExitTree[j].Balance)
*exit = syncBatch.ExitTree[j] *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.Batch, syncBatch.Batch)
assert.Equal(t, batch, syncBatch) assert.Equal(t, batch, syncBatch)
assert.Equal(t, &batch.Batch, dbBatch) //nolint:gosec 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{nil}, freeze defined L1UserTxs{2}
> batchL1 // forge L1UserTxs{2}, freeze defined L1UserTxs{nil} > batchL1 // forge L1UserTxs{2}, freeze defined L1UserTxs{nil}
> block // blockNum=3 > block // blockNum=3
` `
tc := til.NewContext(common.RollupConstMaxL1UserTx) tc := til.NewContext(common.RollupConstMaxL1UserTx)
tilCfgExtra := til.ConfigExtra{
BootCoordAddr: bootCoordAddr,
CoordUser: "A",
}
blocks, err := tc.GenerateBlocks(set1) blocks, err := tc.GenerateBlocks(set1)
require.Nil(t, err) require.Nil(t, err)
// Sanity check // 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 // Add block data to the smart contracts
for _, block := range blocks { for _, block := range blocks {
for _, token := range block.Rollup.AddedTokens { for _, token := range block.Rollup.AddedTokens {
@ -352,12 +348,12 @@ func TestSync(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
} }
client.CtlSetAddr(bootCoordAddr) 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 { for _, batch := range block.Rollup.Batches {
_, err := client.RollupForgeBatch(&eth.RollupForgeBatchArgs{ _, err := client.RollupForgeBatch(&eth.RollupForgeBatchArgs{
NewLastIdx: batch.Batch.LastIdx, NewLastIdx: batch.Batch.LastIdx,
@ -366,7 +362,7 @@ func TestSync(t *testing.T) {
L1CoordinatorTxs: batch.L1CoordinatorTxs, L1CoordinatorTxs: batch.L1CoordinatorTxs,
L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty
L2TxsData: batch.L2Txs, L2TxsData: batch.L2Txs,
FeeIdxCoordinator: feeIdxCoordinator,
FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator,
// Circuit selector // Circuit selector
VerifierIdx: 0, // Intentionally empty VerifierIdx: 0, // Intentionally empty
L1Batch: batch.L1Batch, L1Batch: batch.L1Batch,
@ -380,113 +376,6 @@ func TestSync(t *testing.T) {
client.CtlMineBlock() 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, // Sync to synchronize the current state from the test smart contracts,
// and check the outcome // and check the outcome

+ 239
- 7
test/til/txs.go

@ -21,7 +21,10 @@ func newBatchData(batchNum int) common.BatchData {
L2Txs: []common.L2Tx{}, L2Txs: []common.L2Tx{},
Batch: common.Batch{ Batch: common.Batch{
BatchNum: common.BatchNum(batchNum), 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 // Context contains the data of the test
type Context struct { type Context struct {
Instructions []instruction Instructions []instruction
userNames []string userNames []string
Users map[string]*User
Users map[string]*User // Name -> *User
usersByIdx map[int]*User
accountsByIdx map[int]*Account
LastRegisteredTokenID common.TokenID 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 Maximum L1-user transactions allowed to be queued in a batch
rollupConstMaxL1UserTx int rollupConstMaxL1UserTx int
@ -59,6 +71,8 @@ type Context struct {
l2Txs []L2Tx l2Txs []L2Tx
} }
blockNum int64 blockNum int64
extra contextExtra
} }
// NewContext returns a new Context // NewContext returns a new Context
@ -67,6 +81,8 @@ func NewContext(rollupConstMaxL1UserTx int) *Context {
return &Context{ return &Context{
Users: make(map[string]*User), Users: make(map[string]*User),
l1CreatedAccounts: make(map[string]*Account), l1CreatedAccounts: make(map[string]*Account),
usersByIdx: make(map[int]*User),
accountsByIdx: make(map[int]*Account),
LastRegisteredTokenID: 0, LastRegisteredTokenID: 0,
rollupConstMaxL1UserTx: rollupConstMaxL1UserTx, rollupConstMaxL1UserTx: rollupConstMaxL1UserTx,
@ -82,17 +98,26 @@ func NewContext(rollupConstMaxL1UserTx int) *Context {
openToForge: 1, openToForge: 1,
//nolint:gomnd //nolint:gomnd
blockNum: 2, // rollup genesis blockNum 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 // Account contains the data related to the account for a specific TokenID of a User
type Account struct { 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 // User contains the data related to a testing user
type User struct { type User struct {
Name string
BJJ *babyjub.PrivateKey BJJ *babyjub.PrivateKey
Addr ethCommon.Address Addr ethCommon.Address
Accounts map[common.TokenID]*Account 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) 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{ 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.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++ tc.idx++
} }
if isCoordinatorTxs { if isCoordinatorTxs {
@ -606,6 +635,7 @@ func (tc *Context) generateKeys(userNames []string) {
addr := ethCrypto.PubkeyToAddress(key.PublicKey) addr := ethCrypto.PubkeyToAddress(key.PublicKey)
u := User{ u := User{
Name: userNames[i-1],
BJJ: &sk, BJJ: &sk,
Addr: addr, Addr: addr,
Accounts: make(map[common.TokenID]*Account), Accounts: make(map[common.TokenID]*Account),
@ -622,3 +652,205 @@ func L1TxsToCommonL1Txs(l1 []L1Tx) []common.L1Tx {
} }
return r 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