mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #261 from hermeznetwork/feature/til-extra
Move logic to extend til blocks to til
This commit is contained in:
@@ -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"`
|
BatchNum BatchNum `meddler:"batch_num"`
|
||||||
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum block in which the batch is forged
|
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum block in which the batch is forged
|
||||||
ForgerAddr ethCommon.Address `meddler:"forger_addr"`
|
ForgerAddr ethCommon.Address `meddler:"forger_addr"`
|
||||||
CollectedFees map[TokenID]*big.Int `meddler:"fees_collected,json"`
|
CollectedFees map[TokenID]*big.Int `meddler:"fees_collected,json"`
|
||||||
StateRoot *big.Int `meddler:"state_root,bigint"`
|
FeeIdxsCoordinator []Idx `meddler:"fee_idxs_coordinator,json"`
|
||||||
NumAccounts int `meddler:"num_accounts"`
|
StateRoot *big.Int `meddler:"state_root,bigint"`
|
||||||
LastIdx int64 `meddler:"last_idx"`
|
NumAccounts int `meddler:"num_accounts"`
|
||||||
ExitRoot *big.Int `meddler:"exit_root,bigint"`
|
LastIdx int64 `meddler:"last_idx"`
|
||||||
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.
|
ExitRoot *big.Int `meddler:"exit_root,bigint"`
|
||||||
SlotNum int64 `meddler:"slot_num"` // Slot in which the batch is forged
|
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.
|
||||||
TotalFeesUSD *float64 `meddler:"total_fees_usd"`
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
BatchNum: batchNum,
|
||||||
EthBlockNum: blockNum,
|
EthBlockNum: blockNum,
|
||||||
ForgerAddr: *sender,
|
ForgerAddr: *sender,
|
||||||
CollectedFees: processTxsOut.CollectedFees,
|
CollectedFees: processTxsOut.CollectedFees,
|
||||||
StateRoot: forgeBatchArgs.NewStRoot,
|
FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
|
||||||
NumAccounts: len(batchData.CreatedAccounts),
|
StateRoot: forgeBatchArgs.NewStRoot,
|
||||||
LastIdx: forgeBatchArgs.NewLastIdx,
|
NumAccounts: len(batchData.CreatedAccounts),
|
||||||
ExitRoot: forgeBatchArgs.NewExitRoot,
|
LastIdx: forgeBatchArgs.NewLastIdx,
|
||||||
SlotNum: slotNum,
|
ExitRoot: forgeBatchArgs.NewExitRoot,
|
||||||
|
SlotNum: slotNum,
|
||||||
}
|
}
|
||||||
nextForgeL1TxsNumCpy := nextForgeL1TxsNum
|
nextForgeL1TxsNumCpy := nextForgeL1TxsNum
|
||||||
if forgeBatchArgs.L1Batch {
|
if forgeBatchArgs.L1Batch {
|
||||||
|
|||||||
@@ -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{}
|
// feeIdxCoordinator := []common.Idx{}
|
||||||
if block.Block.EthBlockNum > 2 {
|
// if block.Block.EthBlockNum > 2 {
|
||||||
// After blockNum=2 we have some accounts, use them as
|
// // After blockNum=2 we have some accounts, use them as
|
||||||
// coordinator owned to receive fees.
|
// // coordinator owned to receive fees.
|
||||||
feeIdxCoordinator = []common.Idx{common.Idx(256), common.Idx(259)}
|
// feeIdxCoordinator = []common.Idx{common.Idx(256), common.Idx(259)}
|
||||||
}
|
// }
|
||||||
for _, batch := range block.Rollup.Batches {
|
for _, batch := range block.Rollup.Batches {
|
||||||
_, err := client.RollupForgeBatch(ð.RollupForgeBatchArgs{
|
_, err := client.RollupForgeBatch(ð.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
|
||||||
|
|||||||
246
test/til/txs.go
246
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
|
Idx common.Idx
|
||||||
Nonce common.Nonce
|
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),
|
Idx: common.Idx(tc.idx),
|
||||||
Nonce: common.Nonce(0),
|
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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user