Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: finality gadget client #7

Merged
merged 2 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .envrc.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ export L1_BLOCK_TIME=12
export L2_CHAIN_ID=42069
export L2_BLOCK_TIME=2

##################################################
# babylon Configuration #
##################################################

# Babylonchain finality gadget
export BBN_FINALITY_GADGET_RPC=

##################################################
# op-node Configuration #
##################################################
Expand Down
153 changes: 2 additions & 151 deletions go.mod

Large diffs are not rendered by default.

1,270 changes: 2 additions & 1,268 deletions go.sum

Large diffs are not rendered by default.

46 changes: 19 additions & 27 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,8 @@ type L2VaultsDeployConfig struct {
L1FeeVaultWithdrawalNetwork WithdrawalNetwork `json:"l1FeeVaultWithdrawalNetwork"`
// SequencerFeeVaultWithdrawalNetwork represents the withdrawal network for the SequencerFeeVault.
SequencerFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"sequencerFeeVaultWithdrawalNetwork"`
// BabylonFinalityGadgetChainID is the Chain ID of the Babylon chain for the Babylon finality gadget
BabylonFinalityGadgetChainID string `json:"babylonFinalityGadgetChainID"`
// BabylonFinalityGadgetContractAddress is the contract address for the Babylon finality gadget on Babylon chain.
BabylonFinalityGadgetContractAddress string `json:"babylonFinalityGadgetContractAddress"`
// BabylonFinalityGadgetBitcoinRpc is the Bitcoin RPC URL for the Babylon finality gadget.
BabylonFinalityGadgetBitcoinRpc string `json:"babylonFinalityGadgetBitcoinRpc"`
// BabylonFinalityGadgetRpc is the RPC URL for the Babylon finality gadget.
BabylonFinalityGadgetRpc string `json:"babylonFinalityGadgetRpc"`
}

var _ ConfigChecker = (*L2VaultsDeployConfig)(nil)
Expand Down Expand Up @@ -870,27 +866,23 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
GasLimit: uint64(d.L2GenesisBlockGasLimit),
},
},
BlockTime: d.L2BlockTime,
MaxSequencerDrift: d.MaxSequencerDrift,
SeqWindowSize: d.SequencerWindowSize,
ChannelTimeout: d.ChannelTimeout,
L1ChainID: new(big.Int).SetUint64(d.L1ChainID),
L2ChainID: new(big.Int).SetUint64(d.L2ChainID),
BatchInboxAddress: d.BatchInboxAddress,
DepositContractAddress: d.OptimismPortalProxy,
L1SystemConfigAddress: d.SystemConfigProxy,
RegolithTime: d.RegolithTime(l1StartBlock.Time()),
CanyonTime: d.CanyonTime(l1StartBlock.Time()),
DeltaTime: d.DeltaTime(l1StartBlock.Time()),
EcotoneTime: d.EcotoneTime(l1StartBlock.Time()),
FjordTime: d.FjordTime(l1StartBlock.Time()),
InteropTime: d.InteropTime(l1StartBlock.Time()),
PlasmaConfig: plasma,
BabylonConfig: &rollup.BabylonConfig{
ChainID: d.BabylonFinalityGadgetChainID,
ContractAddress: d.BabylonFinalityGadgetContractAddress,
BitcoinRpc: d.BabylonFinalityGadgetBitcoinRpc,
},
BlockTime: d.L2BlockTime,
MaxSequencerDrift: d.MaxSequencerDrift,
SeqWindowSize: d.SequencerWindowSize,
ChannelTimeout: d.ChannelTimeout,
L1ChainID: new(big.Int).SetUint64(d.L1ChainID),
L2ChainID: new(big.Int).SetUint64(d.L2ChainID),
BatchInboxAddress: d.BatchInboxAddress,
DepositContractAddress: d.OptimismPortalProxy,
L1SystemConfigAddress: d.SystemConfigProxy,
RegolithTime: d.RegolithTime(l1StartBlock.Time()),
CanyonTime: d.CanyonTime(l1StartBlock.Time()),
DeltaTime: d.DeltaTime(l1StartBlock.Time()),
EcotoneTime: d.EcotoneTime(l1StartBlock.Time()),
FjordTime: d.FjordTime(l1StartBlock.Time()),
InteropTime: d.InteropTime(l1StartBlock.Time()),
PlasmaConfig: plasma,
BabylonFinalityGadgetRpc: d.BabylonFinalityGadgetRpc,
}, nil
}

Expand Down
38 changes: 17 additions & 21 deletions op-e2e/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,27 +578,23 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
L2Time: uint64(cfg.DeployConfig.L1GenesisBlockTimestamp),
SystemConfig: e2eutils.SystemConfigFromDeployConfig(cfg.DeployConfig),
},
BlockTime: cfg.DeployConfig.L2BlockTime,
MaxSequencerDrift: cfg.DeployConfig.MaxSequencerDrift,
SeqWindowSize: cfg.DeployConfig.SequencerWindowSize,
ChannelTimeout: cfg.DeployConfig.ChannelTimeout,
L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(),
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
DepositContractAddress: cfg.DeployConfig.OptimismPortalProxy,
L1SystemConfigAddress: cfg.DeployConfig.SystemConfigProxy,
RegolithTime: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
CanyonTime: cfg.DeployConfig.CanyonTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
DeltaTime: cfg.DeployConfig.DeltaTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
EcotoneTime: cfg.DeployConfig.EcotoneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy,
BabylonConfig: &rollup.BabylonConfig{
ChainID: cfg.DeployConfig.BabylonFinalityGadgetChainID,
ContractAddress: cfg.DeployConfig.BabylonFinalityGadgetContractAddress,
BitcoinRpc: cfg.DeployConfig.BabylonFinalityGadgetBitcoinRpc,
},
BlockTime: cfg.DeployConfig.L2BlockTime,
MaxSequencerDrift: cfg.DeployConfig.MaxSequencerDrift,
SeqWindowSize: cfg.DeployConfig.SequencerWindowSize,
ChannelTimeout: cfg.DeployConfig.ChannelTimeout,
L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(),
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
DepositContractAddress: cfg.DeployConfig.OptimismPortalProxy,
L1SystemConfigAddress: cfg.DeployConfig.SystemConfigProxy,
RegolithTime: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
CanyonTime: cfg.DeployConfig.CanyonTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
DeltaTime: cfg.DeployConfig.DeltaTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
EcotoneTime: cfg.DeployConfig.EcotoneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy,
BabylonFinalityGadgetRpc: cfg.DeployConfig.BabylonFinalityGadgetRpc,
}
}
defaultConfig := makeRollupConfig()
Expand Down
26 changes: 26 additions & 0 deletions op-node/rollup/finality/expected_clients.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package finality

import "github.com/babylonlabs-io/finality-gadget/types"

type IFinalityGadgetClient interface {
/// QueryIsBlockBabylonFinalized checks if the given L2 block is finalized by the Babylon finality gadget
QueryIsBlockBabylonFinalized(block *types.Block) (bool, error)

/// QueryBlockRangeBabylonFinalized searches for a row of consecutive finalized blocks in the block range, and returns
QueryBlockRangeBabylonFinalized(blocks []*types.Block) (*uint64, error)

/// QueryBtcStakingActivatedTimestamp returns the timestamp when the BTC staking is activated
QueryBtcStakingActivatedTimestamp() (uint64, error)

/// QueryIsBlockFinalizedByHeight returns the btc finalization status of a block at given height by querying the local db
QueryIsBlockFinalizedByHeight(height uint64) (bool, error)

/// QueryIsBlockFinalizedByHash returns the btc finalization status of a block at given hash by querying the local db
QueryIsBlockFinalizedByHash(hash string) (bool, error)

/// QueryLatestFinalizedBlock returns the latest finalized block by querying the local db
QueryLatestFinalizedBlock() (*types.Block, error)

// Closes the client
Close() error
}
34 changes: 9 additions & 25 deletions op-node/rollup/finality/finalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/event"
"github.com/ethereum-optimism/optimism/op-service/eth"

"github.com/babylonlabs-io/finality-gadget/sdk/btcclient"
sdkclient "github.com/babylonlabs-io/finality-gadget/sdk/client"
sdkcfg "github.com/babylonlabs-io/finality-gadget/sdk/config"
"github.com/babylonlabs-io/finality-gadget/sdk/cwclient"
fgclient "github.com/babylonlabs-io/finality-gadget/client"
fgtypes "github.com/babylonlabs-io/finality-gadget/types"
)

// defaultFinalityLookback defines the amount of L1<>L2 relations to track for finalization purposes, one per L1 block.
Expand Down Expand Up @@ -76,11 +74,6 @@ type FinalizerL2Interface interface {
L2BlockRefByNumber(context.Context, uint64) (eth.L2BlockRef, error)
}

type BabylonFinalityClient interface {
QueryBlockRangeBabylonFinalized(queryBlocks []*cwclient.L2Block) (*uint64, error)
QueryBtcStakingActivatedTimestamp() (uint64, error)
}

type Finalizer struct {
mu sync.Mutex

Expand Down Expand Up @@ -111,27 +104,18 @@ type Finalizer struct {
l2Fetcher FinalizerL2Interface

// babylonFinalityClient is the Babylon DA SDK client
babylonFinalityClient BabylonFinalityClient
babylonFinalityClient IFinalityGadgetClient
}

func NewFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, l1Fetcher FinalizerL1Interface, l2Fetcher FinalizerL2Interface) *Finalizer {
lookback := calcFinalityLookback(cfg)

// Initialize the Babylon Finality client
btcConfig := btcclient.DefaultBTCConfig()
btcConfig.RPCHost = cfg.BabylonConfig.BitcoinRpc
config := &sdkcfg.Config{
ChainID: cfg.BabylonConfig.ChainID,
ContractAddr: cfg.BabylonConfig.ContractAddress,
BTCConfig: btcConfig,
}
// Initialize the Babylon finality gadget client
log.Debug(
"creating Babylon Finality client",
"chain_id", config.ChainID,
"contract_address", config.ContractAddr,
"btc_rpc_host", config.BTCConfig.RPCHost,
"rpc_addr", cfg.BabylonFinalityGadgetRpc,
)
babylonFinalityClient, err := sdkclient.NewClient(config)
babylonFinalityClient, err := fgclient.NewFinalityGadgetGrpcClient(cfg.BabylonFinalityGadgetRpc)
if err != nil {
log.Error("failed to initialize Babylon Finality client", "error", err)
return nil
Expand Down Expand Up @@ -248,7 +232,7 @@ func (fi *Finalizer) tryFinalize() {
defer fi.mu.Unlock()

gadgetActivatedTimestamp, err := fi.babylonFinalityClient.QueryBtcStakingActivatedTimestamp()
if err != nil && !errors.Is(err, sdkclient.ErrBtcStakingNotActivated) {
if err != nil && !errors.Is(err, fgtypes.ErrBtcStakingNotActivated) {
fi.emitter.Emit(rollup.CriticalErrorEvent{Err: fmt.Errorf("failed to query BTC staking activated timestamp: %w", err)})
return
}
Expand Down Expand Up @@ -332,7 +316,7 @@ func (fi *Finalizer) findLastBtcFinalizedL2Block(
) *eth.L2BlockRef {
blockCount := int(fdL2BlockNumber - finalizedL2Number)
l2Blocks := make(map[uint64]eth.L2BlockRef)
queryBlocks := make([]*cwclient.L2Block, 0, blockCount)
queryBlocks := make([]*fgtypes.Block, 0, blockCount)
var largestNonActivatedBlock *eth.L2BlockRef

for i := 0; i < blockCount; i++ {
Expand All @@ -356,7 +340,7 @@ func (fi *Finalizer) findLastBtcFinalizedL2Block(
continue
}

queryBlocks = append(queryBlocks, &cwclient.L2Block{
queryBlocks = append(queryBlocks, &fgtypes.Block{
BlockHeight: l2Block.Number,
BlockHash: l2Block.Hash.String(),
BlockTimestamp: l2Block.Time,
Expand Down
Loading