Skip to content

Commit

Permalink
fix(gas-oracle): fetch base fee from the latest L1 block (#920)
Browse files Browse the repository at this point in the history
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 5, 2023
1 parent f4663fd commit 25b956f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
2 changes: 1 addition & 1 deletion common/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"runtime/debug"
)

var tag = "v4.2.20"
var tag = "v4.2.21"

var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {
Expand Down
9 changes: 6 additions & 3 deletions rollup/cmd/gas_oracle/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/urfave/cli/v2"

"scroll-tech/common/database"
Expand Down Expand Up @@ -92,14 +93,16 @@ func action(ctx *cli.Context) error {
}
// Start l1 watcher process
go utils.LoopWithContext(subCtx, 10*time.Second, func(ctx context.Context) {
number, loopErr := butils.GetLatestConfirmedBlockNumber(ctx, l1client, cfg.L1Config.Confirmations)
// Fetch the latest block number to decrease the delay when fetching gas prices
// Use latest block number - 1 to prevent frequent reorg
number, loopErr := butils.GetLatestConfirmedBlockNumber(ctx, l1client, rpc.LatestBlockNumber)
if loopErr != nil {
log.Error("failed to get block number", "err", loopErr)
return
}

if loopErr = l1watcher.FetchBlockHeader(number); loopErr != nil {
log.Error("Failed to fetch L1 block header", "lastest", number, "err", loopErr)
if loopErr = l1watcher.FetchBlockHeader(number - 1); loopErr != nil {
log.Error("Failed to fetch L1 block header", "lastest", number-1, "err", loopErr)
}
})

Expand Down
27 changes: 19 additions & 8 deletions rollup/internal/orm/l1_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,30 @@ func (o *L1Block) GetL1Blocks(ctx context.Context, fields map[string]interface{}
return l1Blocks, nil
}

// InsertL1Blocks batch insert l1 blocks
// InsertL1Blocks batch inserts l1 blocks.
// If there's a block number conflict (e.g., due to reorg), soft deletes the existing block and inserts the new one.
func (o *L1Block) InsertL1Blocks(ctx context.Context, blocks []L1Block) error {
if len(blocks) == 0 {
return nil
}

db := o.db.WithContext(ctx)
db = db.Model(&L1Block{})

if err := db.Create(&blocks).Error; err != nil {
return fmt.Errorf("L1Block.InsertL1Blocks error: %w", err)
}
return nil
return o.db.Transaction(func(tx *gorm.DB) error {
var blockNumbers []uint64
for _, block := range blocks {
blockNumbers = append(blockNumbers, block.Number)
}

db := tx.WithContext(ctx)
db = db.Model(&L1Block{})
if err := db.Where("number IN (?)", blockNumbers).Delete(&L1Block{}).Error; err != nil {
return fmt.Errorf("L1Block.InsertL1Blocks error: soft deleting blocks failed, block numbers: %v, error: %w", blockNumbers, err)
}

if err := db.Create(&blocks).Error; err != nil {
return fmt.Errorf("L1Block.InsertL1Blocks error: %w", err)
}
return nil
})
}

// UpdateL1GasOracleStatusAndOracleTxHash update l1 gas oracle status and oracle tx hash
Expand Down
45 changes: 45 additions & 0 deletions rollup/internal/orm/orm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,51 @@ func tearDownEnv(t *testing.T) {
base.Free()
}

func TestL1BlockOrm(t *testing.T) {
sqlDB, err := db.DB()
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(sqlDB))

l1BlockOrm := NewL1Block(db)

// mock blocks
block1 := L1Block{Number: 1, Hash: "hash1"}
block2 := L1Block{Number: 2, Hash: "hash2"}
block2AfterReorg := L1Block{Number: 2, Hash: "hash3"}

err = l1BlockOrm.InsertL1Blocks(context.Background(), []L1Block{block1, block2})
assert.NoError(t, err)

height, err := l1BlockOrm.GetLatestL1BlockHeight(context.Background())
assert.NoError(t, err)
assert.Equal(t, uint64(2), height)

blocks, err := l1BlockOrm.GetL1Blocks(context.Background(), map[string]interface{}{})
assert.NoError(t, err)
assert.Len(t, blocks, 2)
assert.Equal(t, "hash1", blocks[0].Hash)
assert.Equal(t, "hash2", blocks[1].Hash)

// reorg handling: insert another block with same height and different hash
err = l1BlockOrm.InsertL1Blocks(context.Background(), []L1Block{block2AfterReorg})
assert.NoError(t, err)

blocks, err = l1BlockOrm.GetL1Blocks(context.Background(), map[string]interface{}{})
assert.NoError(t, err)
assert.Len(t, blocks, 2)
assert.Equal(t, "hash1", blocks[0].Hash)
assert.Equal(t, "hash3", blocks[1].Hash)

err = l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(context.Background(), "hash1", types.GasOracleImported, "txhash1")
assert.NoError(t, err)

updatedBlocks, err := l1BlockOrm.GetL1Blocks(context.Background(), map[string]interface{}{})
assert.NoError(t, err)
assert.Len(t, updatedBlocks, 2)
assert.Equal(t, types.GasOracleImported, types.GasOracleStatus(updatedBlocks[0].GasOracleStatus))
assert.Equal(t, "txhash1", updatedBlocks[0].OracleTxHash)
}

func TestL2BlockOrm(t *testing.T) {
sqlDB, err := db.DB()
assert.NoError(t, err)
Expand Down

0 comments on commit 25b956f

Please sign in to comment.