mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #481 from hermeznetwork/feature/set-idx-new-accounts
Add idx for txs that create account
This commit is contained in:
@@ -268,6 +268,10 @@ func TestMain(m *testing.M) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
err = tcc.FillBlocksForgedL1UserTxs(blocksData)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
AddAditionalInformation(blocksData)
|
AddAditionalInformation(blocksData)
|
||||||
// Generate L2 Txs with til
|
// Generate L2 Txs with til
|
||||||
commonPoolTxs, err := tcc.GeneratePoolL2Txs(txsets.SetPoolL2MinimumFlow0)
|
commonPoolTxs, err := tcc.GeneratePoolL2Txs(txsets.SetPoolL2MinimumFlow0)
|
||||||
@@ -304,6 +308,7 @@ func TestMain(m *testing.M) {
|
|||||||
// Insert block into HistoryDB
|
// Insert block into HistoryDB
|
||||||
// nolint reason: block is used as read only in the function
|
// nolint reason: block is used as read only in the function
|
||||||
if err := api.h.AddBlockSCData(&block); err != nil { //nolint:gosec
|
if err := api.h.AddBlockSCData(&block); err != nil { //nolint:gosec
|
||||||
|
log.Error(err)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// Extract data
|
// Extract data
|
||||||
@@ -329,7 +334,6 @@ func TestMain(m *testing.M) {
|
|||||||
testTokens = append(testTokens, token)
|
testTokens = append(testTokens, token)
|
||||||
}
|
}
|
||||||
// Set USD value for tokens in DB
|
// Set USD value for tokens in DB
|
||||||
commonL1Txs = append(commonL1Txs, block.Rollup.L1UserTxs...)
|
|
||||||
for _, batch := range block.Rollup.Batches {
|
for _, batch := range block.Rollup.Batches {
|
||||||
commonL2Txs = append(commonL2Txs, batch.L2Txs...)
|
commonL2Txs = append(commonL2Txs, batch.L2Txs...)
|
||||||
for i := range batch.CreatedAccounts {
|
for i := range batch.CreatedAccounts {
|
||||||
@@ -338,6 +342,7 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
commonBatches = append(commonBatches, batch.Batch)
|
commonBatches = append(commonBatches, batch.Batch)
|
||||||
commonExitTree = append(commonExitTree, batch.ExitTree...)
|
commonExitTree = append(commonExitTree, batch.ExitTree...)
|
||||||
|
commonL1Txs = append(commonL1Txs, batch.L1UserTxs...)
|
||||||
commonL1Txs = append(commonL1Txs, batch.L1CoordinatorTxs...)
|
commonL1Txs = append(commonL1Txs, batch.L1CoordinatorTxs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func genTestTxs(
|
|||||||
tx.BatchNum = &bn
|
tx.BatchNum = &bn
|
||||||
}
|
}
|
||||||
// If FromIdx is not nil
|
// If FromIdx is not nil
|
||||||
idxStr := idxToHez(l1.FromIdx, token.Symbol)
|
idxStr := idxToHez(l1.EffectiveFromIdx, token.Symbol)
|
||||||
tx.FromIdx = &idxStr
|
tx.FromIdx = &idxStr
|
||||||
// If tx has a normal ToIdx (>255), set FromEthAddr and FromBJJ
|
// If tx has a normal ToIdx (>255), set FromEthAddr and FromBJJ
|
||||||
if l1.ToIdx >= common.UserThreshold {
|
if l1.ToIdx >= common.UserThreshold {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type L1Tx struct {
|
|||||||
Position int `meddler:"position"`
|
Position int `meddler:"position"`
|
||||||
UserOrigin bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
UserOrigin bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||||
FromIdx Idx `meddler:"from_idx,zeroisnull"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.DepositAmount (deposit)
|
FromIdx Idx `meddler:"from_idx,zeroisnull"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.DepositAmount (deposit)
|
||||||
|
EffectiveFromIdx Idx `meddler:"effective_from_idx,zeroisnull"`
|
||||||
FromEthAddr ethCommon.Address `meddler:"from_eth_addr,zeroisnull"`
|
FromEthAddr ethCommon.Address `meddler:"from_eth_addr,zeroisnull"`
|
||||||
FromBJJ babyjub.PublicKeyComp `meddler:"from_bjj,zeroisnull"`
|
FromBJJ babyjub.PublicKeyComp `meddler:"from_bjj,zeroisnull"`
|
||||||
ToIdx Idx `meddler:"to_idx"` // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
ToIdx Idx `meddler:"to_idx"` // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
||||||
|
|||||||
@@ -851,6 +851,15 @@ func (hdb *HistoryDB) addL1Txs(d meddler.DB, l1txs []common.L1Tx) error {
|
|||||||
amountFloat, _ := af.Float64()
|
amountFloat, _ := af.Float64()
|
||||||
laf := new(big.Float).SetInt(l1txs[i].DepositAmount)
|
laf := new(big.Float).SetInt(l1txs[i].DepositAmount)
|
||||||
depositAmountFloat, _ := laf.Float64()
|
depositAmountFloat, _ := laf.Float64()
|
||||||
|
var effectiveFromIdx *common.Idx
|
||||||
|
if l1txs[i].UserOrigin {
|
||||||
|
if l1txs[i].Type != common.TxTypeCreateAccountDeposit &&
|
||||||
|
l1txs[i].Type != common.TxTypeCreateAccountDepositTransfer {
|
||||||
|
effectiveFromIdx = &l1txs[i].FromIdx
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
effectiveFromIdx = &l1txs[i].EffectiveFromIdx
|
||||||
|
}
|
||||||
txs = append(txs, txWrite{
|
txs = append(txs, txWrite{
|
||||||
// Generic
|
// Generic
|
||||||
IsL1: true,
|
IsL1: true,
|
||||||
@@ -858,6 +867,7 @@ func (hdb *HistoryDB) addL1Txs(d meddler.DB, l1txs []common.L1Tx) error {
|
|||||||
Type: l1txs[i].Type,
|
Type: l1txs[i].Type,
|
||||||
Position: l1txs[i].Position,
|
Position: l1txs[i].Position,
|
||||||
FromIdx: &l1txs[i].FromIdx,
|
FromIdx: &l1txs[i].FromIdx,
|
||||||
|
EffectiveFromIdx: effectiveFromIdx,
|
||||||
ToIdx: l1txs[i].ToIdx,
|
ToIdx: l1txs[i].ToIdx,
|
||||||
Amount: l1txs[i].Amount,
|
Amount: l1txs[i].Amount,
|
||||||
AmountFloat: amountFloat,
|
AmountFloat: amountFloat,
|
||||||
@@ -894,6 +904,7 @@ func (hdb *HistoryDB) addL2Txs(d meddler.DB, l2txs []common.L2Tx) error {
|
|||||||
Type: l2txs[i].Type,
|
Type: l2txs[i].Type,
|
||||||
Position: l2txs[i].Position,
|
Position: l2txs[i].Position,
|
||||||
FromIdx: &l2txs[i].FromIdx,
|
FromIdx: &l2txs[i].FromIdx,
|
||||||
|
EffectiveFromIdx: &l2txs[i].FromIdx,
|
||||||
ToIdx: l2txs[i].ToIdx,
|
ToIdx: l2txs[i].ToIdx,
|
||||||
Amount: l2txs[i].Amount,
|
Amount: l2txs[i].Amount,
|
||||||
AmountFloat: amountFloat,
|
AmountFloat: amountFloat,
|
||||||
@@ -919,6 +930,7 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
|
|||||||
type,
|
type,
|
||||||
position,
|
position,
|
||||||
from_idx,
|
from_idx,
|
||||||
|
effective_from_idx,
|
||||||
to_idx,
|
to_idx,
|
||||||
amount,
|
amount,
|
||||||
amount_f,
|
amount_f,
|
||||||
@@ -938,17 +950,6 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// // GetTxs returns a list of txs from the DB
|
|
||||||
// func (hdb *HistoryDB) GetTxs() ([]common.Tx, error) {
|
|
||||||
// var txs []*common.Tx
|
|
||||||
// err := meddler.QueryAll(
|
|
||||||
// hdb.db, &txs,
|
|
||||||
// `SELECT * FROM tx
|
|
||||||
// ORDER BY (batch_num, position) ASC`,
|
|
||||||
// )
|
|
||||||
// return db.SlicePtrsToSlice(txs).([]common.Tx), err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GetHistoryTx returns a tx from the DB given a TxID
|
// GetHistoryTx returns a tx from the DB given a TxID
|
||||||
func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*TxAPI, error) {
|
func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*TxAPI, error) {
|
||||||
// Warning: amount_success and deposit_amount_success have true as default for
|
// Warning: amount_success and deposit_amount_success have true as default for
|
||||||
@@ -957,7 +958,7 @@ func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*TxAPI, error) {
|
|||||||
tx := &TxAPI{}
|
tx := &TxAPI{}
|
||||||
err := meddler.QueryRow(
|
err := meddler.QueryRow(
|
||||||
hdb.db, tx, `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
hdb.db, tx, `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
||||||
hez_idx(tx.from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
hez_idx(tx.effective_from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
||||||
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
||||||
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
||||||
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
||||||
@@ -988,7 +989,7 @@ func (hdb *HistoryDB) GetHistoryTxs(
|
|||||||
var query string
|
var query string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
queryStr := `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
queryStr := `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
||||||
hez_idx(tx.from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
hez_idx(tx.effective_from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
||||||
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
||||||
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
||||||
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
||||||
@@ -1028,7 +1029,7 @@ func (hdb *HistoryDB) GetHistoryTxs(
|
|||||||
} else {
|
} else {
|
||||||
queryStr += "WHERE "
|
queryStr += "WHERE "
|
||||||
}
|
}
|
||||||
queryStr += "(tx.from_idx = ? OR tx.to_idx = ?) "
|
queryStr += "(tx.effective_from_idx = ? OR tx.to_idx = ?) "
|
||||||
args = append(args, idx, idx)
|
args = append(args, idx, idx)
|
||||||
nextIsAnd = true
|
nextIsAnd = true
|
||||||
}
|
}
|
||||||
@@ -1245,7 +1246,7 @@ func (hdb *HistoryDB) GetAllL1UserTxs() ([]common.L1Tx, error) {
|
|||||||
err := meddler.QueryAll(
|
err := meddler.QueryAll(
|
||||||
hdb.db, &txs, // Note that '\x' gets parsed as a big.Int with value = 0
|
hdb.db, &txs, // Note that '\x' gets parsed as a big.Int with value = 0
|
||||||
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
|
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
|
||||||
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
|
tx.from_idx, tx.effective_from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
|
||||||
tx.amount, (CASE WHEN tx.batch_num IS NULL THEN NULL WHEN tx.amount_success THEN tx.amount ELSE '\x' END) AS effective_amount,
|
tx.amount, (CASE WHEN tx.batch_num IS NULL THEN NULL WHEN tx.amount_success THEN tx.amount ELSE '\x' END) AS effective_amount,
|
||||||
tx.deposit_amount, (CASE WHEN tx.batch_num IS NULL THEN NULL WHEN tx.deposit_amount_success THEN tx.deposit_amount ELSE '\x' END) AS effective_deposit_amount,
|
tx.deposit_amount, (CASE WHEN tx.batch_num IS NULL THEN NULL WHEN tx.deposit_amount_success THEN tx.deposit_amount ELSE '\x' END) AS effective_deposit_amount,
|
||||||
tx.eth_block_num, tx.type, tx.batch_num
|
tx.eth_block_num, tx.type, tx.batch_num
|
||||||
@@ -1262,7 +1263,7 @@ func (hdb *HistoryDB) GetAllL1CoordinatorTxs() ([]common.L1Tx, error) {
|
|||||||
err := meddler.QueryAll(
|
err := meddler.QueryAll(
|
||||||
hdb.db, &txs,
|
hdb.db, &txs,
|
||||||
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
|
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
|
||||||
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
|
tx.from_idx, tx.effective_from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
|
||||||
tx.amount, tx.amount AS effective_amount,
|
tx.amount, tx.amount AS effective_amount,
|
||||||
tx.deposit_amount, tx.deposit_amount AS effective_deposit_amount,
|
tx.deposit_amount, tx.deposit_amount AS effective_deposit_amount,
|
||||||
tx.eth_block_num, tx.type, tx.batch_num
|
tx.eth_block_num, tx.type, tx.batch_num
|
||||||
@@ -1480,19 +1481,21 @@ func (hdb *HistoryDB) SetInitialSCVars(rollup *common.RollupVariables,
|
|||||||
return tracerr.Wrap(txn.Commit())
|
return tracerr.Wrap(txn.Commit())
|
||||||
}
|
}
|
||||||
|
|
||||||
// setL1UserTxEffectiveAmounts sets the EffectiveAmount and EffectiveDepositAmount
|
// setExtraInfoForgedL1UserTxs sets the EffectiveAmount, EffectiveDepositAmount
|
||||||
// of the given l1UserTxs (with an UPDATE)
|
// and EffectiveFromIdx of the given l1UserTxs (with an UPDATE)
|
||||||
func (hdb *HistoryDB) setL1UserTxEffectiveAmounts(d sqlx.Ext, txs []common.L1Tx) error {
|
func (hdb *HistoryDB) setExtraInfoForgedL1UserTxs(d sqlx.Ext, txs []common.L1Tx) error {
|
||||||
if len(txs) == 0 {
|
if len(txs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Effective amounts are stored as success flags in the DB, with true value by default
|
// Effective amounts are stored as success flags in the DB, with true value by default
|
||||||
// to reduce the amount of updates. Therefore, only amounts that became uneffective should be
|
// to reduce the amount of updates. Therefore, only amounts that became uneffective should be
|
||||||
// updated to become false
|
// updated to become false. At the same time, all the txs that contain
|
||||||
|
// accounts (FromIdx == 0) are updated to set the EffectiveFromIdx.
|
||||||
type txUpdate struct {
|
type txUpdate struct {
|
||||||
ID common.TxID `db:"id"`
|
ID common.TxID `db:"id"`
|
||||||
AmountSuccess bool `db:"amount_success"`
|
AmountSuccess bool `db:"amount_success"`
|
||||||
DepositAmountSuccess bool `db:"deposit_amount_success"`
|
DepositAmountSuccess bool `db:"deposit_amount_success"`
|
||||||
|
EffectiveFromIdx common.Idx `db:"effective_from_idx"`
|
||||||
}
|
}
|
||||||
txUpdates := []txUpdate{}
|
txUpdates := []txUpdate{}
|
||||||
equal := func(a *big.Int, b *big.Int) bool {
|
equal := func(a *big.Int, b *big.Int) bool {
|
||||||
@@ -1501,22 +1504,24 @@ func (hdb *HistoryDB) setL1UserTxEffectiveAmounts(d sqlx.Ext, txs []common.L1Tx)
|
|||||||
for i := range txs {
|
for i := range txs {
|
||||||
amountSuccess := equal(txs[i].Amount, txs[i].EffectiveAmount)
|
amountSuccess := equal(txs[i].Amount, txs[i].EffectiveAmount)
|
||||||
depositAmountSuccess := equal(txs[i].DepositAmount, txs[i].EffectiveDepositAmount)
|
depositAmountSuccess := equal(txs[i].DepositAmount, txs[i].EffectiveDepositAmount)
|
||||||
if !amountSuccess || !depositAmountSuccess {
|
if !amountSuccess || !depositAmountSuccess || txs[i].FromIdx == 0 {
|
||||||
txUpdates = append(txUpdates, txUpdate{
|
txUpdates = append(txUpdates, txUpdate{
|
||||||
ID: txs[i].TxID,
|
ID: txs[i].TxID,
|
||||||
AmountSuccess: amountSuccess,
|
AmountSuccess: amountSuccess,
|
||||||
DepositAmountSuccess: depositAmountSuccess,
|
DepositAmountSuccess: depositAmountSuccess,
|
||||||
|
EffectiveFromIdx: txs[i].EffectiveFromIdx,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const query string = `
|
const query string = `
|
||||||
UPDATE tx SET
|
UPDATE tx SET
|
||||||
amount_success = tx_update.amount_success,
|
amount_success = tx_update.amount_success,
|
||||||
deposit_amount_success = tx_update.deposit_amount_success
|
deposit_amount_success = tx_update.deposit_amount_success,
|
||||||
|
effective_from_idx = tx_update.effective_from_idx
|
||||||
FROM (VALUES
|
FROM (VALUES
|
||||||
(NULL::::BYTEA, NULL::::BOOL, NULL::::BOOL),
|
(NULL::::BYTEA, NULL::::BOOL, NULL::::BOOL, NULL::::BIGINT),
|
||||||
(:id, :amount_success, :deposit_amount_success)
|
(:id, :amount_success, :deposit_amount_success, :effective_from_idx)
|
||||||
) as tx_update (id, amount_success, deposit_amount_success)
|
) as tx_update (id, amount_success, deposit_amount_success, effective_from_idx)
|
||||||
WHERE tx.id = tx_update.id;
|
WHERE tx.id = tx_update.id;
|
||||||
`
|
`
|
||||||
if len(txUpdates) > 0 {
|
if len(txUpdates) > 0 {
|
||||||
@@ -1599,14 +1604,14 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
|
|||||||
return tracerr.Wrap(err)
|
return tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the EffectiveAmount and EffectiveDepositAmount of all the
|
// Add accounts
|
||||||
// L1UserTxs that have been forged in this batch
|
if err := hdb.addAccounts(txn, batch.CreatedAccounts); err != nil {
|
||||||
if err = hdb.setL1UserTxEffectiveAmounts(txn, batch.L1UserTxs); err != nil {
|
|
||||||
return tracerr.Wrap(err)
|
return tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add accounts
|
// Set the EffectiveAmount and EffectiveDepositAmount of all the
|
||||||
if err := hdb.addAccounts(txn, batch.CreatedAccounts); err != nil {
|
// L1UserTxs that have been forged in this batch
|
||||||
|
if err = hdb.setExtraInfoForgedL1UserTxs(txn, batch.L1UserTxs); err != nil {
|
||||||
return tracerr.Wrap(err)
|
return tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -752,7 +752,7 @@ func TestSetInitialSCVars(t *testing.T) {
|
|||||||
require.Equal(t, wDelayer, dbWDelayer)
|
require.Equal(t, wDelayer, dbWDelayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetL1UserTxEffectiveAmounts(t *testing.T) {
|
func TestSetExtraInfoForgedL1UserTxs(t *testing.T) {
|
||||||
test.WipeDB(historyDB.DB())
|
test.WipeDB(historyDB.DB())
|
||||||
|
|
||||||
set := `
|
set := `
|
||||||
@@ -789,11 +789,12 @@ func TestSetL1UserTxEffectiveAmounts(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
// Add second batch to trigger the update of the batch_num,
|
// Add second batch to trigger the update of the batch_num,
|
||||||
// while avoiding the implicit call of setL1UserTxEffectiveAmounts
|
// while avoiding the implicit call of setExtraInfoForgedL1UserTxs
|
||||||
err = historyDB.addBlock(historyDB.db, &blocks[1].Block)
|
err = historyDB.addBlock(historyDB.db, &blocks[1].Block)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = historyDB.addBatch(historyDB.db, &blocks[1].Rollup.Batches[0].Batch)
|
err = historyDB.addBatch(historyDB.db, &blocks[1].Rollup.Batches[0].Batch)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
err = historyDB.addAccounts(historyDB.db, blocks[1].Rollup.Batches[0].CreatedAccounts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Set the Effective{Amount,DepositAmount} of the L1UserTxs that are forged in the second block
|
// Set the Effective{Amount,DepositAmount} of the L1UserTxs that are forged in the second block
|
||||||
@@ -803,7 +804,7 @@ func TestSetL1UserTxEffectiveAmounts(t *testing.T) {
|
|||||||
l1Txs[1].EffectiveAmount = big.NewInt(0)
|
l1Txs[1].EffectiveAmount = big.NewInt(0)
|
||||||
l1Txs[2].EffectiveDepositAmount = big.NewInt(0)
|
l1Txs[2].EffectiveDepositAmount = big.NewInt(0)
|
||||||
l1Txs[2].EffectiveAmount = big.NewInt(0)
|
l1Txs[2].EffectiveAmount = big.NewInt(0)
|
||||||
err = historyDB.setL1UserTxEffectiveAmounts(historyDB.db, l1Txs)
|
err = historyDB.setExtraInfoForgedL1UserTxs(historyDB.db, l1Txs)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
dbL1Txs, err := historyDB.GetAllL1UserTxs()
|
dbL1Txs, err := historyDB.GetAllL1UserTxs()
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ type txWrite struct {
|
|||||||
Type common.TxType `meddler:"type"`
|
Type common.TxType `meddler:"type"`
|
||||||
Position int `meddler:"position"`
|
Position int `meddler:"position"`
|
||||||
FromIdx *common.Idx `meddler:"from_idx"`
|
FromIdx *common.Idx `meddler:"from_idx"`
|
||||||
|
EffectiveFromIdx *common.Idx `meddler:"effective_from_idx"`
|
||||||
ToIdx common.Idx `meddler:"to_idx"`
|
ToIdx common.Idx `meddler:"to_idx"`
|
||||||
Amount *big.Int `meddler:"amount,bigint"`
|
Amount *big.Int `meddler:"amount,bigint"`
|
||||||
AmountFloat float64 `meddler:"amount_f"`
|
AmountFloat float64 `meddler:"amount_f"`
|
||||||
@@ -375,24 +376,24 @@ type RollupVariablesAPI struct {
|
|||||||
// AuctionVariablesAPI are the variables of the Auction Smart Contract
|
// AuctionVariablesAPI are the variables of the Auction Smart Contract
|
||||||
type AuctionVariablesAPI struct {
|
type AuctionVariablesAPI struct {
|
||||||
EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"`
|
EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"`
|
||||||
// Donation Address
|
// DonationAddress Address where the donations will be sent
|
||||||
DonationAddress ethCommon.Address `json:"donationAddress" meddler:"donation_address" validate:"required"`
|
DonationAddress ethCommon.Address `json:"donationAddress" meddler:"donation_address" validate:"required"`
|
||||||
// Boot Coordinator Address
|
// BootCoordinator Address of the boot coordinator
|
||||||
BootCoordinator ethCommon.Address `json:"bootCoordinator" meddler:"boot_coordinator" validate:"required"`
|
BootCoordinator ethCommon.Address `json:"bootCoordinator" meddler:"boot_coordinator" validate:"required"`
|
||||||
// Boot Coordinator URL
|
// BootCoordinatorURL URL of the boot coordinator
|
||||||
BootCoordinatorURL string `json:"bootCoordinatorUrl" meddler:"boot_coordinator_url" validate:"required"`
|
BootCoordinatorURL string `json:"bootCoordinatorUrl" meddler:"boot_coordinator_url" validate:"required"`
|
||||||
// The minimum bid value in a series of 6 slots
|
// DefaultSlotSetBid The minimum bid value in a series of 6 slots
|
||||||
DefaultSlotSetBid [6]*apitypes.BigIntStr `json:"defaultSlotSetBid" meddler:"default_slot_set_bid,json" validate:"required"`
|
DefaultSlotSetBid [6]*apitypes.BigIntStr `json:"defaultSlotSetBid" meddler:"default_slot_set_bid,json" validate:"required"`
|
||||||
// SlotNum at which the new default_slot_set_bid applies
|
// DefaultSlotSetBidSlotNum SlotNum at which the new default_slot_set_bid applies
|
||||||
DefaultSlotSetBidSlotNum int64 `json:"defaultSlotSetBidSlotNum" meddler:"default_slot_set_bid_slot_num"`
|
DefaultSlotSetBidSlotNum int64 `json:"defaultSlotSetBidSlotNum" meddler:"default_slot_set_bid_slot_num"`
|
||||||
// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
|
// ClosedAuctionSlots Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
|
||||||
ClosedAuctionSlots uint16 `json:"closedAuctionSlots" meddler:"closed_auction_slots" validate:"required"`
|
ClosedAuctionSlots uint16 `json:"closedAuctionSlots" meddler:"closed_auction_slots" validate:"required"`
|
||||||
// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
|
// OpenAuctionSlots Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
|
||||||
OpenAuctionSlots uint16 `json:"openAuctionSlots" meddler:"open_auction_slots" validate:"required"`
|
OpenAuctionSlots uint16 `json:"openAuctionSlots" meddler:"open_auction_slots" validate:"required"`
|
||||||
// How the HEZ tokens deposited by the slot winner are distributed (Burn: 40% - Donation: 40% - HGT: 20%)
|
// AllocationRatio How the HEZ tokens deposited by the slot winner are distributed (Burn: 40% - Donation: 40% - HGT: 20%)
|
||||||
AllocationRatio [3]uint16 `json:"allocationRatio" meddler:"allocation_ratio,json" validate:"required"`
|
AllocationRatio [3]uint16 `json:"allocationRatio" meddler:"allocation_ratio,json" validate:"required"`
|
||||||
// Minimum outbid (percentage) over the previous one to consider it valid
|
// Outbidding Minimum outbid (percentage) over the previous one to consider it valid
|
||||||
Outbidding uint16 `json:"outbidding" meddler:"outbidding" validate:"required"`
|
Outbidding uint16 `json:"outbidding" meddler:"outbidding" validate:"required"`
|
||||||
// Number of blocks at the end of a slot in which any coordinator can forge if the winner has not forged one before
|
// SlotDeadline Number of blocks at the end of a slot in which any coordinator can forge if the winner has not forged one before
|
||||||
SlotDeadline uint8 `json:"slotDeadline" meddler:"slot_deadline" validate:"required"`
|
SlotDeadline uint8 `json:"slotDeadline" meddler:"slot_deadline" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ CREATE TABLE tx (
|
|||||||
type VARCHAR(40) NOT NULL,
|
type VARCHAR(40) NOT NULL,
|
||||||
position INT NOT NULL,
|
position INT NOT NULL,
|
||||||
from_idx BIGINT,
|
from_idx BIGINT,
|
||||||
|
effective_from_idx BIGINT REFERENCES account (idx) ON DELETE SET NULL,
|
||||||
from_eth_addr BYTEA,
|
from_eth_addr BYTEA,
|
||||||
from_bjj BYTEA,
|
from_bjj BYTEA,
|
||||||
to_idx BIGINT NOT NULL,
|
to_idx BIGINT NOT NULL,
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) {
|
|||||||
|
|
||||||
sync, err := synchronizer.NewSynchronizer(client, historyDB, stateDB, synchronizer.Config{
|
sync, err := synchronizer.NewSynchronizer(client, historyDB, stateDB, synchronizer.Config{
|
||||||
StatsRefreshPeriod: cfg.Synchronizer.StatsRefreshPeriod.Duration,
|
StatsRefreshPeriod: cfg.Synchronizer.StatsRefreshPeriod.Duration,
|
||||||
|
ChainID: chainIDU16,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tracerr.Wrap(err)
|
return nil, tracerr.Wrap(err)
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ type SCConsts struct {
|
|||||||
// Config is the Synchronizer configuration
|
// Config is the Synchronizer configuration
|
||||||
type Config struct {
|
type Config struct {
|
||||||
StatsRefreshPeriod time.Duration
|
StatsRefreshPeriod time.Duration
|
||||||
|
ChainID uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronizer implements the Synchronizer type
|
// Synchronizer implements the Synchronizer type
|
||||||
@@ -797,17 +798,21 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e
|
|||||||
// Transform L2 txs to PoolL2Txs
|
// Transform L2 txs to PoolL2Txs
|
||||||
poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
|
poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
|
||||||
|
|
||||||
// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
|
if int(forgeBatchArgs.VerifierIdx) >= len(s.consts.Rollup.Verifiers) {
|
||||||
//nolint:gomnd
|
return nil, tracerr.Wrap(fmt.Errorf("forgeBatchArgs.VerifierIdx (%v) >= "+
|
||||||
tpc := txprocessor.Config{ // TODO TMP
|
" len(s.consts.Rollup.Verifiers) (%v)",
|
||||||
NLevels: 32,
|
forgeBatchArgs.VerifierIdx, len(s.consts.Rollup.Verifiers)))
|
||||||
MaxFeeTx: 64,
|
}
|
||||||
MaxTx: 512,
|
tpc := txprocessor.Config{
|
||||||
MaxL1Tx: 64,
|
NLevels: uint32(s.consts.Rollup.Verifiers[forgeBatchArgs.VerifierIdx].NLevels),
|
||||||
ChainID: uint16(0),
|
MaxTx: uint32(s.consts.Rollup.Verifiers[forgeBatchArgs.VerifierIdx].MaxTx),
|
||||||
|
ChainID: s.cfg.ChainID,
|
||||||
|
MaxFeeTx: common.RollupConstMaxFeeIdxCoordinator,
|
||||||
|
MaxL1Tx: common.RollupConstMaxL1Tx,
|
||||||
}
|
}
|
||||||
tp := txprocessor.NewTxProcessor(s.stateDB, tpc)
|
tp := txprocessor.NewTxProcessor(s.stateDB, tpc)
|
||||||
|
|
||||||
|
// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
|
||||||
processTxsOut, err := tp.ProcessTxs(forgeBatchArgs.FeeIdxCoordinator,
|
processTxsOut, err := tp.ProcessTxs(forgeBatchArgs.FeeIdxCoordinator,
|
||||||
l1UserTxs, batchData.L1CoordinatorTxs, poolL2Txs)
|
l1UserTxs, batchData.L1CoordinatorTxs, poolL2Txs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -98,6 +98,11 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
|
|||||||
tx.Position == _dbTx.Position {
|
tx.Position == _dbTx.Position {
|
||||||
dbTx = new(common.L1Tx)
|
dbTx = new(common.L1Tx)
|
||||||
*dbTx = _dbTx
|
*dbTx = _dbTx
|
||||||
|
// NOTE: Overwrite EffectiveFromIdx in L1UserTx
|
||||||
|
// from db because we don't expect
|
||||||
|
// EffectiveFromIdx to be set yet, as this tx
|
||||||
|
// is not in yet forged
|
||||||
|
dbTx.EffectiveFromIdx = 0
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +147,18 @@ func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBloc
|
|||||||
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
|
||||||
|
assert.Equal(t, len(batch.L1UserTxs), len(syncBatch.L1UserTxs))
|
||||||
|
// NOTE: EffectiveFromIdx is set to til L1UserTxs in
|
||||||
|
// `FillBlocksForgedL1UserTxs` function
|
||||||
|
for j := range syncBatch.L1UserTxs {
|
||||||
|
assert.NotEqual(t, 0, syncBatch.L1UserTxs[j].EffectiveFromIdx)
|
||||||
|
}
|
||||||
assert.Equal(t, batch.L1UserTxs, syncBatch.L1UserTxs)
|
assert.Equal(t, batch.L1UserTxs, syncBatch.L1UserTxs)
|
||||||
|
// NOTE: EffectiveFromIdx is set to til L1CoordinatorTxs in
|
||||||
|
// `FillBlocksExtra` function
|
||||||
|
for j := range syncBatch.L1CoordinatorTxs {
|
||||||
|
assert.NotEqual(t, 0, syncBatch.L1CoordinatorTxs[j].EffectiveFromIdx)
|
||||||
|
}
|
||||||
assert.Equal(t, batch.L1CoordinatorTxs, syncBatch.L1CoordinatorTxs)
|
assert.Equal(t, batch.L1CoordinatorTxs, syncBatch.L1CoordinatorTxs)
|
||||||
assert.Equal(t, batch.L2Txs, syncBatch.L2Txs)
|
assert.Equal(t, batch.L2Txs, syncBatch.L2Txs)
|
||||||
// In exit tree, we only check AccountIdx and Balance, because
|
// In exit tree, we only check AccountIdx and Balance, because
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type contextExtra struct {
|
|||||||
toForgeL1TxsNum int64
|
toForgeL1TxsNum int64
|
||||||
nonces map[common.Idx]common.Nonce
|
nonces map[common.Idx]common.Nonce
|
||||||
idx int
|
idx int
|
||||||
|
idxByTxID map[common.TxID]common.Idx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context contains the data of the test
|
// Context contains the data of the test
|
||||||
@@ -107,6 +108,7 @@ func NewContext(chainID uint16, rollupConstMaxL1UserTx int) *Context {
|
|||||||
toForgeL1TxsNum: 0,
|
toForgeL1TxsNum: 0,
|
||||||
nonces: make(map[common.Idx]common.Nonce),
|
nonces: make(map[common.Idx]common.Nonce),
|
||||||
idx: common.UserThreshold,
|
idx: common.UserThreshold,
|
||||||
|
idxByTxID: make(map[common.TxID]common.Idx),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -762,7 +764,12 @@ func (tc *Context) FillBlocksL1UserTxsBatchNum(blocks []common.BlockData) {
|
|||||||
|
|
||||||
// FillBlocksForgedL1UserTxs fills the L1UserTxs of a batch with the L1UserTxs
|
// FillBlocksForgedL1UserTxs fills the L1UserTxs of a batch with the L1UserTxs
|
||||||
// that are forged in that batch. It always sets `EffectiveAmount` = `Amount`
|
// that are forged in that batch. It always sets `EffectiveAmount` = `Amount`
|
||||||
// and `EffectiveDepositAmount` = `DepositAmount`.
|
// and `EffectiveDepositAmount` = `DepositAmount`. This function requires a
|
||||||
|
// previous call to `FillBlocksExtra`.
|
||||||
|
// - blocks[].Rollup.L1UserTxs[].BatchNum
|
||||||
|
// - blocks[].Rollup.L1UserTxs[].EffectiveAmount
|
||||||
|
// - blocks[].Rollup.L1UserTxs[].EffectiveDepositAmount
|
||||||
|
// - blocks[].Rollup.L1UserTxs[].EffectiveFromIdx
|
||||||
func (tc *Context) FillBlocksForgedL1UserTxs(blocks []common.BlockData) error {
|
func (tc *Context) FillBlocksForgedL1UserTxs(blocks []common.BlockData) error {
|
||||||
for i := range blocks {
|
for i := range blocks {
|
||||||
block := &blocks[i]
|
block := &blocks[i]
|
||||||
@@ -783,6 +790,11 @@ func (tc *Context) FillBlocksForgedL1UserTxs(blocks []common.BlockData) error {
|
|||||||
return tracerr.Wrap(err)
|
return tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
*tx = *_tx
|
*tx = *_tx
|
||||||
|
if tx.FromIdx == 0 {
|
||||||
|
tx.EffectiveFromIdx = tc.extra.idxByTxID[tx.TxID]
|
||||||
|
} else {
|
||||||
|
tx.EffectiveFromIdx = tx.FromIdx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -802,6 +814,7 @@ func (tc *Context) FillBlocksForgedL1UserTxs(blocks []common.BlockData) error {
|
|||||||
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].Position
|
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].Position
|
||||||
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EffectiveAmount
|
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EffectiveAmount
|
||||||
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EffectiveDepositAmount
|
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EffectiveDepositAmount
|
||||||
|
// - blocks[].Rollup.Batch.L1CoordinatorTxs[].EffectiveFromIdx
|
||||||
// - blocks[].Rollup.Batch.L2Txs[].TxID
|
// - blocks[].Rollup.Batch.L2Txs[].TxID
|
||||||
// - blocks[].Rollup.Batch.L2Txs[].Position
|
// - blocks[].Rollup.Batch.L2Txs[].Position
|
||||||
// - blocks[].Rollup.Batch.L2Txs[].Nonce
|
// - blocks[].Rollup.Batch.L2Txs[].Nonce
|
||||||
@@ -839,15 +852,17 @@ func (tc *Context) FillBlocksExtra(blocks []common.BlockData, cfg *ConfigExtra)
|
|||||||
block := &blocks[i]
|
block := &blocks[i]
|
||||||
for j := range block.Rollup.Batches {
|
for j := range block.Rollup.Batches {
|
||||||
batch := &block.Rollup.Batches[j]
|
batch := &block.Rollup.Batches[j]
|
||||||
l1Txs := []common.L1Tx{}
|
l1Txs := []*common.L1Tx{}
|
||||||
if batch.L1Batch {
|
if batch.L1Batch {
|
||||||
for _, tx := range tc.Queues[*batch.Batch.ForgeL1TxsNum] {
|
for k := range tc.Queues[*batch.Batch.ForgeL1TxsNum] {
|
||||||
l1Txs = append(l1Txs, tx.L1Tx)
|
l1Txs = append(l1Txs, &tc.Queues[*batch.Batch.ForgeL1TxsNum][k].L1Tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l1Txs = append(l1Txs, batch.L1CoordinatorTxs...)
|
for k := range batch.L1CoordinatorTxs {
|
||||||
|
l1Txs = append(l1Txs, &batch.L1CoordinatorTxs[k])
|
||||||
|
}
|
||||||
for k := range l1Txs {
|
for k := range l1Txs {
|
||||||
tx := &l1Txs[k]
|
tx := l1Txs[k]
|
||||||
if tx.Type == common.TxTypeCreateAccountDeposit ||
|
if tx.Type == common.TxTypeCreateAccountDeposit ||
|
||||||
tx.Type == common.TxTypeCreateAccountDepositTransfer {
|
tx.Type == common.TxTypeCreateAccountDepositTransfer {
|
||||||
user, ok := tc.UsersByIdx[tc.extra.idx]
|
user, ok := tc.UsersByIdx[tc.extra.idx]
|
||||||
@@ -864,6 +879,10 @@ func (tc *Context) FillBlocksExtra(blocks []common.BlockData, cfg *ConfigExtra)
|
|||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
Balance: big.NewInt(0),
|
Balance: big.NewInt(0),
|
||||||
})
|
})
|
||||||
|
if !tx.UserOrigin {
|
||||||
|
tx.EffectiveFromIdx = common.Idx(tc.extra.idx)
|
||||||
|
}
|
||||||
|
tc.extra.idxByTxID[tx.TxID] = common.Idx(tc.extra.idx)
|
||||||
tc.extra.idx++
|
tc.extra.idx++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,10 +154,14 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tracerr.Wrap(err)
|
return nil, tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
if tp.s.Typ == statedb.TypeSynchronizer && createdAccount != nil {
|
if tp.s.Typ == statedb.TypeSynchronizer {
|
||||||
|
if createdAccount != nil {
|
||||||
createdAccounts = append(createdAccounts, *createdAccount)
|
createdAccounts = append(createdAccounts, *createdAccount)
|
||||||
|
l1usertxs[i].EffectiveFromIdx = createdAccount.Idx
|
||||||
|
} else {
|
||||||
|
l1usertxs[i].EffectiveFromIdx = l1usertxs[i].FromIdx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tp.zki != nil {
|
if tp.zki != nil {
|
||||||
l1TxData, err := l1usertxs[i].BytesGeneric()
|
l1TxData, err := l1usertxs[i].BytesGeneric()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -201,8 +205,13 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
|||||||
if exitIdx != nil {
|
if exitIdx != nil {
|
||||||
log.Error("Unexpected Exit in L1CoordinatorTx")
|
log.Error("Unexpected Exit in L1CoordinatorTx")
|
||||||
}
|
}
|
||||||
if tp.s.Typ == statedb.TypeSynchronizer && createdAccount != nil {
|
if tp.s.Typ == statedb.TypeSynchronizer {
|
||||||
|
if createdAccount != nil {
|
||||||
createdAccounts = append(createdAccounts, *createdAccount)
|
createdAccounts = append(createdAccounts, *createdAccount)
|
||||||
|
l1coordinatortxs[i].EffectiveFromIdx = createdAccount.Idx
|
||||||
|
} else {
|
||||||
|
l1coordinatortxs[i].EffectiveFromIdx = l1coordinatortxs[i].FromIdx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if tp.zki != nil {
|
if tp.zki != nil {
|
||||||
l1TxData, err := l1coordinatortxs[i].BytesGeneric()
|
l1TxData, err := l1coordinatortxs[i].BytesGeneric()
|
||||||
|
|||||||
Reference in New Issue
Block a user