diff --git a/Cargo.lock b/Cargo.lock index f4581347f4..cabac84f83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9802,7 +9802,6 @@ dependencies = [ name = "rooch-finality" version = "0.8.0" dependencies = [ - "accumulator", "anyhow 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", "async-trait", "coerce", @@ -9815,11 +9814,9 @@ dependencies = [ "prost-build 0.13.3", "prost-types 0.13.3", "protox", - "raw-store", "rooch-config", "rooch-db", "rooch-event", - "rooch-genesis", "rooch-store", "rooch-types", "serde 1.0.215", diff --git a/crates/rooch-db/src/lib.rs b/crates/rooch-db/src/lib.rs index 5e354f91d0..a667dc5485 100644 --- a/crates/rooch-db/src/lib.rs +++ b/crates/rooch-db/src/lib.rs @@ -33,6 +33,7 @@ use rooch_store::{ RoochStore, META_SEQUENCER_INFO_COLUMN_FAMILY_NAME, STATE_CHANGE_SET_COLUMN_FAMILY_NAME, TRANSACTION_COLUMN_FAMILY_NAME, TX_SEQUENCE_INFO_MAPPING_COLUMN_FAMILY_NAME, }; +use rooch_types::finality_block::L2BlockRef; use rooch_types::indexer::state::{ collect_revert_object_change_ids, handle_revert_object_change, IndexerObjectStateChangeSet, IndexerObjectStatesIndexGenerator, @@ -409,4 +410,9 @@ impl RoochDB { // TODO repair the changeset sync and indexer store Ok((issues, fixed)) } + + //TODO implements this after proposer generate blocks + pub fn l2_block_ref_by_number(&self, block_number: u64) -> Result { + return Ok(L2BlockRef::default()); + } } diff --git a/crates/rooch-finality/Cargo.toml b/crates/rooch-finality/Cargo.toml index e740d50ee8..38f4b073f7 100644 --- a/crates/rooch-finality/Cargo.toml +++ b/crates/rooch-finality/Cargo.toml @@ -22,29 +22,24 @@ tracing = { workspace = true } prometheus = { workspace = true } function_name = { workspace = true } tonic = { workspace = true, features = ["codegen", "prost"] } -#tonic = { version = "0.12.3", features = ["codegen", "prost"]} prost = { workspace = true } prost-types = { workspace = true } #protobuf = { workspace = true } moveos-types = { workspace = true } moveos-eventbus = { workspace = true } -accumulator = { workspace = true } metrics = { workspace = true } -raw-store = { workspace = true } rooch-types = { workspace = true } rooch-store = { workspace = true } rooch-config = { workspace = true } rooch-db = { workspace = true } -rooch-genesis = { workspace = true } rooch-event = { workspace = true } [build-dependencies] prost-build = { workspace = true } prost-types = { workspace = true } protox = "0.7.1" -#tonic-build = { version = "0.12.3", features = [ "prost" ]} tonic-build = { workspace = true, features = [ "prost" ]} #[target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/crates/rooch-finality/build.rs b/crates/rooch-finality/build.rs index 60dd97b999..c959fb20d5 100644 --- a/crates/rooch-finality/build.rs +++ b/crates/rooch-finality/build.rs @@ -1,10 +1,9 @@ -//! A build script generating rust types from protobuf definitions. - // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 +//! A build script generating rust types from protobuf definitions. + use prost_types::FileDescriptorSet; -use std::collections::HashSet; static OUT_DIR: &str = "src/proto"; const PROTO_FILES: &[&str] = &[ @@ -25,6 +24,7 @@ fn protox_compile() -> FileDescriptorSet { protox::compile(PROTO_FILES, INCLUDES).expect("protox failed to build") } +#[allow(dead_code)] // #[cfg(not(feature = "tonic"))] fn prost_build(fds: FileDescriptorSet) { let mut config = prost_build::Config::new(); @@ -43,7 +43,7 @@ fn tonic_build(fds: FileDescriptorSet) { let mut prost_config = prost_build::Config::new(); prost_config.enable_type_names(); - let mut tonic_config = tonic_build::configure() + let tonic_config = tonic_build::configure() // .include_file("mod.rs") .build_client(true) .build_server(false) diff --git a/crates/rooch-finality/src/actor/finality.rs b/crates/rooch-finality/src/actor/finality.rs new file mode 100644 index 0000000000..293df7c12a --- /dev/null +++ b/crates/rooch-finality/src/actor/finality.rs @@ -0,0 +1,146 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use std::ops::Deref; +use std::sync::Arc; +use std::time::SystemTime; + +use crate::finality::finalizer::{Config, Finalizer, FinalizerL1Mock}; +use crate::messages::FinalityMessage; +use crate::metrics::FinalityMetrics; +use anyhow::{anyhow, Result}; +use async_trait::async_trait; +use coerce::actor::{context::ActorContext, message::Handler, Actor, LocalActorRef}; +use function_name::named; +use moveos_eventbus::bus::EventData; +use prometheus::Registry; +use rooch_db::RoochDB; +use rooch_event::actor::{EventActor, EventActorSubscribeMessage}; +use rooch_event::event::ServiceStatusEvent; +use rooch_types::finality_block::Block; +use rooch_types::service_status::ServiceStatus; +use tracing::info; + +pub struct FinalityActor { + // rooch_store: RoochStore, + finalizer: Finalizer, + rooch_db: RoochDB, + service_status: ServiceStatus, + metrics: Arc, + event_actor: Option>, +} + +impl FinalityActor { + pub fn new( + rooch_db: RoochDB, + service_status: ServiceStatus, + registry: &Registry, + event_actor: Option>, + ) -> Result { + let babylon_finality_gadget_rpc_str = ""; + let config = Config { + babylon_finality_gadget_rpc: babylon_finality_gadget_rpc_str.to_string(), + }; + //TODO implements finalize L1 service + let finalizer_L1_Mock = Arc::new(FinalizerL1Mock::default()); + let finalizer = Finalizer::new(&config, finalizer_L1_Mock, rooch_db.clone()) + .map_err(|e| anyhow!(format!("New finality actor error: {:?}", e)))?; + + Ok(Self { + finalizer, + rooch_db, + service_status, + metrics: Arc::new(FinalityMetrics::new(registry)), + event_actor, + }) + } + + pub async fn subscribe_event( + &self, + event_actor_ref: LocalActorRef, + executor_actor_ref: LocalActorRef, + ) { + let service_status_event = ServiceStatusEvent::default(); + let actor_subscribe_message = EventActorSubscribeMessage::new( + service_status_event, + "finality".to_string(), + Box::new(executor_actor_ref), + ); + let _ = event_actor_ref.send(actor_subscribe_message).await; + } + + #[named] + pub async fn finality(&mut self, block: Block) -> Result<()> { + let fn_name = function_name!(); + let _timer = self + .metrics + .finality_latency_seconds + .with_label_values(&[fn_name]) + .start_timer(); + + // match self.service_status { + // ServiceStatus::ReadOnlyMode => { + // return Err(anyhow::anyhow!("The service is in read-only mode")); + // } + // ServiceStatus::DateImportMode => { + // if !tx_data.is_l1_block() && !tx_data.is_l1_tx() { + // return Err(anyhow::anyhow!( + // "The service is in date import mode, only allow l1 block and l1 tx" + // )); + // } + // } + // ServiceStatus::Maintenance => { + // // Only the sequencer can send transactions in maintenance mode + // if let Some(sender) = tx_data.sender() { + // if sender != self.sequencer_key.public().rooch_address()? { + // return Err(anyhow::anyhow!("The service is in maintenance mode")); + // } + // } else { + // return Err(anyhow::anyhow!("The service is in maintenance mode")); + // } + // } + // _ => {} + // } + + let now = SystemTime::now(); + let _tx_timestamp = now.duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as u64; + + self.finalizer.try_finalize().await?; + info!( + "rooch finality finalize block_hash: {} block_number: {:?}", + block.block_hash, block.block_height + ); + + Ok(()) + } +} + +#[async_trait] +impl Actor for FinalityActor { + async fn started(&mut self, ctx: &mut ActorContext) { + let local_actor_ref: LocalActorRef = ctx.actor_ref(); + if let Some(event_actor) = self.event_actor.clone() { + let _ = self.subscribe_event(event_actor, local_actor_ref).await; + } + } +} + +#[async_trait] +impl Handler for FinalityActor { + async fn handle(&mut self, msg: FinalityMessage, _ctx: &mut ActorContext) -> Result<()> { + self.finality(msg.block).await + } +} + +#[async_trait] +impl Handler for FinalityActor { + async fn handle(&mut self, msg: EventData, _ctx: &mut ActorContext) -> Result<()> { + if let Ok(service_status_event) = msg.data.downcast::() { + let service_status = service_status_event.deref().status; + tracing::warn!("FinalityActor set self status to {:?}", service_status); + self.service_status = service_status; + } + + Ok(()) + } +} diff --git a/crates/rooch-finality/src/actor/mod.rs b/crates/rooch-finality/src/actor/mod.rs index e35aca1a32..1b3f20e19a 100644 --- a/crates/rooch-finality/src/actor/mod.rs +++ b/crates/rooch-finality/src/actor/mod.rs @@ -1,4 +1,4 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -pub mod sequencer; +pub mod finality; diff --git a/crates/rooch-finality/src/actor/sequencer.rs b/crates/rooch-finality/src/actor/sequencer.rs deleted file mode 100644 index e6fc0d5eaa..0000000000 --- a/crates/rooch-finality/src/actor/sequencer.rs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) RoochNetwork -// SPDX-License-Identifier: Apache-2.0 - -use std::ops::Deref; -use std::sync::Arc; -use std::time::SystemTime; - -use crate::messages::{ - GetSequencerInfoMessage, GetSequencerOrderMessage, GetTransactionByHashMessage, - GetTransactionsByHashMessage, GetTxHashsMessage, TransactionSequenceMessage, -}; -use crate::metrics::SequencerMetrics; -use accumulator::{Accumulator, MerkleAccumulator}; -use anyhow::Result; -use async_trait::async_trait; -use coerce::actor::{context::ActorContext, message::Handler, Actor, LocalActorRef}; -use function_name::named; -use moveos_eventbus::bus::EventData; -use moveos_types::h256::{self, H256}; -use prometheus::Registry; -use rooch_event::actor::{EventActor, EventActorSubscribeMessage}; -use rooch_event::event::ServiceStatusEvent; -use rooch_store::transaction_store::TransactionStore; -use rooch_store::RoochStore; -use rooch_types::crypto::{RoochKeyPair, Signature}; -use rooch_types::sequencer::SequencerInfo; -use rooch_types::service_status::ServiceStatus; -use rooch_types::transaction::{LedgerTransaction, LedgerTxData}; -use tracing::info; - -pub struct SequencerActor { - last_sequencer_info: SequencerInfo, - tx_accumulator: MerkleAccumulator, - sequencer_key: RoochKeyPair, - rooch_store: RoochStore, - service_status: ServiceStatus, - metrics: Arc, - event_actor: Option>, -} - -impl SequencerActor { - pub fn new( - sequencer_key: RoochKeyPair, - rooch_store: RoochStore, - service_status: ServiceStatus, - registry: &Registry, - event_actor: Option>, - ) -> Result { - // The sequencer info would be initialized when genesis, so the sequencer info should not be None - let last_sequencer_info = rooch_store - .get_meta_store() - .get_sequencer_info()? - .ok_or_else(|| anyhow::anyhow!("Load sequencer info failed"))?; - let (last_order, last_accumulator_info) = ( - last_sequencer_info.last_order, - last_sequencer_info.last_accumulator_info.clone(), - ); - info!("Load latest sequencer order {:?}", last_order); - info!( - "Load latest sequencer accumulator info {:?}", - last_accumulator_info - ); - let tx_accumulator = MerkleAccumulator::new_with_info( - last_accumulator_info, - rooch_store.get_transaction_accumulator_store(), - ); - - Ok(Self { - last_sequencer_info, - tx_accumulator, - sequencer_key, - rooch_store, - service_status, - metrics: Arc::new(SequencerMetrics::new(registry)), - event_actor, - }) - } - - pub async fn subscribe_event( - &self, - event_actor_ref: LocalActorRef, - executor_actor_ref: LocalActorRef, - ) { - let service_status_event = ServiceStatusEvent::default(); - let actor_subscribe_message = EventActorSubscribeMessage::new( - service_status_event, - "sequencer".to_string(), - Box::new(executor_actor_ref), - ); - let _ = event_actor_ref.send(actor_subscribe_message).await; - } - - pub fn last_order(&self) -> u64 { - self.last_sequencer_info.last_order - } - - #[named] - pub fn sequence(&mut self, mut tx_data: LedgerTxData) -> Result { - let fn_name = function_name!(); - let _timer = self - .metrics - .sequencer_sequence_latency_seconds - .with_label_values(&[fn_name]) - .start_timer(); - - match self.service_status { - ServiceStatus::ReadOnlyMode => { - return Err(anyhow::anyhow!("The service is in read-only mode")); - } - ServiceStatus::DateImportMode => { - if !tx_data.is_l1_block() && !tx_data.is_l1_tx() { - return Err(anyhow::anyhow!( - "The service is in date import mode, only allow l1 block and l1 tx" - )); - } - } - ServiceStatus::Maintenance => { - // Only the sequencer can send transactions in maintenance mode - if let Some(sender) = tx_data.sender() { - if sender != self.sequencer_key.public().rooch_address()? { - return Err(anyhow::anyhow!("The service is in maintenance mode")); - } - } else { - return Err(anyhow::anyhow!("The service is in maintenance mode")); - } - } - _ => {} - } - - let now = SystemTime::now(); - let tx_timestamp = now.duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as u64; - - let tx_order = self.last_sequencer_info.last_order + 1; - - let tx_hash = tx_data.tx_hash(); - let mut witness_data = tx_hash.as_ref().to_vec(); - witness_data.extend(tx_order.to_le_bytes().iter()); - let witness_hash = h256::sha3_256_of(&witness_data); - let tx_order_signature = Signature::sign(&witness_hash.0, &self.sequencer_key) - .as_ref() - .to_vec(); - - // Calc transaction accumulator - let _tx_accumulator_root = self.tx_accumulator.append(vec![tx_hash].as_slice())?; - let tx_accumulator_unsaved_nodes = self.tx_accumulator.pop_unsaved_nodes(); - - let tx_accumulator_info = self.tx_accumulator.get_info(); - let tx = LedgerTransaction::build_ledger_transaction( - tx_data, - tx_timestamp, - tx_order, - tx_order_signature, - tx_accumulator_info.clone(), - ); - - let sequencer_info = SequencerInfo::new(tx_order, tx_accumulator_info); - self.rooch_store.save_sequenced_tx( - tx_hash, - tx.clone(), - sequencer_info.clone(), - tx_accumulator_unsaved_nodes, - )?; - info!( - "sequencer sequenced tx_hash: {} tx_order: {:?}", - tx_hash, tx_order - ); - self.last_sequencer_info = sequencer_info; - - Ok(tx) - } -} - -#[async_trait] -impl Actor for SequencerActor { - async fn started(&mut self, ctx: &mut ActorContext) { - let local_actor_ref: LocalActorRef = ctx.actor_ref(); - if let Some(event_actor) = self.event_actor.clone() { - let _ = self.subscribe_event(event_actor, local_actor_ref).await; - } - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - msg: TransactionSequenceMessage, - _ctx: &mut ActorContext, - ) -> Result { - self.sequence(msg.tx) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - msg: GetTransactionByHashMessage, - _ctx: &mut ActorContext, - ) -> Result> { - self.rooch_store.get_transaction_by_hash(msg.hash) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - msg: GetTransactionsByHashMessage, - _ctx: &mut ActorContext, - ) -> Result>> { - self.rooch_store.get_transactions_by_hash(msg.tx_hashes) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - msg: GetTxHashsMessage, - _ctx: &mut ActorContext, - ) -> Result>> { - let GetTxHashsMessage { tx_orders } = msg; - self.rooch_store.get_tx_hashes(tx_orders) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - _msg: GetSequencerOrderMessage, - _ctx: &mut ActorContext, - ) -> Result { - Ok(self.last_sequencer_info.last_order) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle(&mut self, msg: EventData, _ctx: &mut ActorContext) -> Result<()> { - if let Ok(service_status_event) = msg.data.downcast::() { - let service_status = service_status_event.deref().status; - tracing::warn!("SequencerActor set self status to {:?}", service_status); - self.service_status = service_status; - } - - Ok(()) - } -} - -#[async_trait] -impl Handler for SequencerActor { - async fn handle( - &mut self, - _msg: GetSequencerInfoMessage, - _ctx: &mut ActorContext, - ) -> Result { - Ok(self.last_sequencer_info.clone()) - } -} diff --git a/crates/rooch-finality/src/finality/expected_clients.rs b/crates/rooch-finality/src/finality/expected_clients.rs new file mode 100644 index 0000000000..0ad2d2b0fe --- /dev/null +++ b/crates/rooch-finality/src/finality/expected_clients.rs @@ -0,0 +1,31 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Result; +use rooch_types::finality_block::Block; +// This should be updated to match the gRPC interface of the Babylon finality gadget client +// https://github.com/babylonlabs-io/finality-gadget + +/// Trait defining the interface for the Babylon finality gadget client +pub trait FinalityGadgetClient { + /// Checks if the given L2 block is finalized by the Babylon finality gadget + fn query_is_block_babylon_finalized(&self, block: &Block) -> Result; + + /// Searches for a row of consecutive finalized blocks in the block range + fn query_block_range_babylon_finalized(&self, blocks: &[Block]) -> Result>; + + /// Returns the timestamp when the BTC staking is activated + fn query_btc_staking_activated_timestamp(&self) -> Result; + + /// Returns the btc finalization status of a block at given height by querying the local db + fn query_is_block_finalized_by_height(&self, height: u64) -> Result; + + /// Returns the btc finalization status of a block at given hash by querying the local db + fn query_is_block_finalized_by_hash(&self, hash: String) -> Result; + + /// Returns the latest finalized block by querying the local db + fn query_latest_finalized_block(&self) -> Result; + + /// Closes the client + fn close(&self) -> Result<()>; +} diff --git a/crates/rooch-finality/src/finality/finalizer.rs b/crates/rooch-finality/src/finality/finalizer.rs new file mode 100644 index 0000000000..f34cbfcc32 --- /dev/null +++ b/crates/rooch-finality/src/finality/finalizer.rs @@ -0,0 +1,482 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{anyhow, Result}; +use std::sync::{Arc, Mutex}; +use std::time::Duration; +use std::collections::HashMap; +use tracing::{debug, error}; +use async_trait::async_trait; +use rooch_db::RoochDB; +use rooch_types::finality_block::{Block, BlockID, L1BlockRef, L2BlockRef}; +use crate::rpc_client::FinalityGadgetGrpcClient; + +// defaultFinalityLookback defines the amount of L1<>L2 relations to track for finalization purposes, one per L1 block. +// +// When L1 finalizes blocks, it finalizes finalityLookback blocks behind the L1 head. +// Non-finality may take longer, but when it does finalize again, it is within this range of the L1 head. +// Thus we only need to retain the L1<>L2 derivation relation data of this many L1 blocks. +// +// In the event of older finalization signals, misconfiguration, or insufficient L1<>L2 derivation relation data, +// then we may miss the opportunity to finalize more L2 blocks. +// This does not cause any divergence, it just causes lagging finalization status. +// +// The beacon chain on mainnet has 32 slots per epoch, +// and new finalization events happen at most 4 epochs behind the head. +// And then we add 1 to make pruning easier by leaving room for a new item without pruning the 32*4. +const DEFAULT_FINALITY_LOOKBACK: u64 = 4 * 32 + 1; + +// finalityDelay is the number of L1 blocks to traverse before trying to finalize L2 blocks again. +// We do not want to do this too often, since it requires fetching a L1 block by number, so no cache data. +const FINALITY_DELAY: u64 = 64; + +// // Types and Structs +// #[derive(Clone, Debug, Default, PartialEq)] +// pub struct BlockID { +// pub number: u64, +// pub hash: String, +// } +// +// #[derive(Clone, Debug, Default, PartialEq)] +// pub struct L1BlockRef { +// pub hash: String, +// pub number: u64, +// pub time: u64, +// pub parent_hash: String, +// } +// +// #[derive(Clone, Debug, Default, PartialEq)] +// pub struct L2BlockRef { +// pub hash: H256, +// pub number: u64, +// pub time: u64, +// pub parent_hash: H256, +// } + +#[derive(Clone, Debug)] +pub struct FinalityData { + // The last L2 block that was fully derived and inserted into the L2 engine while processing this L1 block. + l2_block: L2BlockRef, + // The L1 block this stage was at when inserting the L2 block. + // When this L1 block is finalized, the L2 chain up to this block can be fully reproduced from finalized L1 data. + l1_block: BlockID, +} + +#[derive(Clone, Debug)] +pub struct Config { + pub babylon_finality_gadget_rpc: String, +} + +// Events +#[derive(Debug)] +pub enum Event { + FinalizeL1(FinalizeL1Event), + SafeDerived(SafeDerivedEvent), + DeriverIdle(DeriverIdleEvent), + Reset(ResetEvent), + TryFinalize, + ForkchoiceUpdate(ForkchoiceUpdateEvent), + CriticalError(CriticalErrorEvent), +} + +#[derive(Debug)] +pub struct FinalizeL1Event { + pub finalized_l1: L1BlockRef, +} + +#[derive(Debug)] +pub struct SafeDerivedEvent { + pub safe: L2BlockRef, + pub derived_from: L1BlockRef, +} + +#[derive(Debug)] +pub struct DeriverIdleEvent { + pub origin: L1BlockRef, +} + +#[derive(Debug)] +pub struct ResetEvent { + pub err: String, +} + +#[derive(Debug)] +pub struct ForkchoiceUpdateEvent { + pub finalized_l2_head: L2BlockRef, +} + +#[derive(Debug)] +pub struct CriticalErrorEvent { + pub err: String, +} + +// Traits +#[async_trait] +pub trait FinalizerEngine: Send + Sync { + fn finalized(&self) -> L2BlockRef; + fn set_finalized_head(&self, head: L2BlockRef); +} + +#[async_trait] +pub trait FinalizerL1Interface: Send + Sync { + async fn l1_block_ref_by_number(&self, number: u64) -> Result>; +} +#[async_trait] +pub trait EventEmitter: Send + Sync { + async fn emit(&self, event: Event); +} + +// Main Finalizer Implementation +pub struct Finalizer { + ctx: Arc>, + emitter: Arc, + finalized_l1: Arc>, + last_finalized_l2: Arc>, + tried_finalize_at: Arc>, + finality_data: Arc>>, + finality_lookback: u64, + l1_fetcher: Arc, + l2_fetcher: RoochDB, + babylon_finality_client: FinalityGadgetGrpcClient, +} + +impl Finalizer { + // calcFinalityLookback calculates the default finality lookback based on DA challenge window if altDA + // mode is activated or L1 finality lookback. + fn calc_finality_lookback(cfg: &Config) -> u64 { + // // in alt-da mode the longest finality lookback is a commitment is challenged on the last block of + // // the challenge window in which case it will be both challenge + resolve window. + // if cfg.alt_da_enabled { + // let lkb = cfg.alt_da_config.da_challenge_window + + // cfg.alt_da_config.da_resolve_window + 1; + // // in the case only if the altDA windows are longer than the default finality lookback + // if lkb > DEFAULT_FINALITY_LOOKBACK { + // return lkb; + // } + // } + DEFAULT_FINALITY_LOOKBACK + } + + pub fn new( + cfg: &Config, + l1_fetcher: Arc, + l2_fetcher: RoochDB, + ) -> Result { + let lookback = Self::calc_finality_lookback(cfg); + + debug!("creating Babylon Finality client, rpc_addr {:?}", cfg.babylon_finality_gadget_rpc); + + let babylon_finality_gadget_client = FinalityGadgetGrpcClient::new(cfg.babylon_finality_gadget_rpc.clone()).await.map_err(|e| anyhow!(format!("New finalizer error: {:?}", e)))?; + + Ok(Finalizer { + ctx: Arc::new(tokio::sync::Mutex::new(())), + emitter: Arc::new(NoopEmitter::default()), + finalized_l1: Arc::new(Mutex::new(L1BlockRef::default())), + last_finalized_l2: Arc::new(Mutex::new(L2BlockRef::default())), + tried_finalize_at: Arc::new(Mutex::new(0)), + finality_data: Arc::new(Mutex::new(Vec::with_capacity(lookback as usize))), + finality_lookback: lookback, + l1_fetcher, + l2_fetcher, + babylon_finality_client: babylon_finality_gadget_client, + }) + } + + pub fn attach_emitter(&mut self, emitter: Arc) { + self.emitter = emitter; + } + + pub fn finalized_l1(&self) -> L1BlockRef { + self.finalized_l1.lock().unwrap().clone() + } + + pub async fn on_event(&mut self, event: Event) -> bool { + match event { + Event::FinalizeL1(ev) => { + self.on_l1_finalized(ev.finalized_l1).await; + true + } + Event::SafeDerived(ev) => { + self.on_derived_safe_block(ev.safe, ev.derived_from).await; + true + } + Event::DeriverIdle(ev) => { + self.on_derivation_idle(ev.origin).await; + true + } + Event::Reset(_) => { + self.on_reset().await; + true + } + Event::TryFinalize => { + self.try_finalize().await; + true + } + Event::ForkchoiceUpdate(ev) => { + *self.last_finalized_l2.lock().unwrap() = ev.finalized_l2_head; + true + } + _ => false, + } + } + + // onL1Finalized applies a L1 finality signal + async fn on_l1_finalized(&self, l1_origin: L1BlockRef) { + let mut finalized_l1 = self.finalized_l1.lock().unwrap(); + let prev_finalized_l1 = finalized_l1.clone(); + + if l1_origin.number < finalized_l1.number { + error!("ignoring old L1 finalized block signal! prev_finalized_l1 {:?}, signaled_finalized_l1 {:?}", prev_finalized_l1, l1_origin); + return; + } + + if *finalized_l1 != l1_origin { + *self.tried_finalize_at.lock().unwrap() = 0; + *finalized_l1 = l1_origin; + } + + self.emitter.emit(Event::TryFinalize).await; + } + + // onDerivationIdle is called when the pipeline is exhausted of new data (i.e. no more L2 blocks to derive from). + async fn on_derivation_idle(&self, derived_from: L1BlockRef) { + let finalized_l1 = self.finalized_l1.lock().unwrap(); + if *finalized_l1 == L1BlockRef::default() { + return; + } + + let tried_finalize_at = *self.tried_finalize_at.lock().unwrap(); + if tried_finalize_at != 0 && derived_from.number <= tried_finalize_at + FINALITY_DELAY { + return; + } + + debug!("processing L1 finality information, l1_finalized {:?}, derived_from {:?}, previous {:?}", finalized_l1, derived_from, tried_finalize_at); + + *self.tried_finalize_at.lock().unwrap() = derived_from.number; + self.emitter.emit(Event::TryFinalize).await; + } + + pub async fn try_finalize(&mut self) -> Result<()>{ + let gadget_activated_timestamp = match self.babylon_finality_client + .query_btc_staking_activated_timestamp() + .await { + Ok(timestamp) => timestamp, + Err(e) if e.to_string().contains("BtcStakingNotActivated") => 0, + Err(e) => { + self.emitter.emit(Event::CriticalError(CriticalErrorEvent { + err: format!("failed to query BTC staking activated timestamp: {}", e.to_string()) + })).await; + return Ok(()); + } + }; + + let mut finalized_l2 = self.last_finalized_l2.lock().unwrap().clone(); + let mut finalized_derived_from = None; + + let finality_data = self.finality_data.lock().unwrap().clone(); + for fd in finality_data.iter() { + if fd.l2_block.number > finalized_l2.number && + fd.l1_block.number <= self.finalized_l1.lock().unwrap().number { + + if let Some(last_finalized_block) = self.find_last_btc_finalized_l2_block( + fd.l2_block.number, + finalized_l2.number, + gadget_activated_timestamp + ).await? { + finalized_l2 = last_finalized_block; + finalized_derived_from = Some(fd.l1_block.clone()); + } + + if finalized_derived_from.is_none() || + finalized_l2.number != fd.l2_block.number { + break; + } + } + } + + if let Some(derived_from) = finalized_derived_from { + let ctx = tokio::time::timeout(Duration::from_secs(10), async { + let signal_ref = self.l1_fetcher + .l1_block_ref_by_number(self.finalized_l1.lock().unwrap().number) + .await?; + + if signal_ref.hash != self.finalized_l1.lock().unwrap().hash { + self.emitter.emit(Event::Reset(ResetEvent { + err: format!( + "need to reset, we assumed {:?} is finalized, but canonical chain is {:?}", + self.finalized_l1.lock().unwrap(), + signal_ref + ) + })).await; + return Err("Chain reset needed".into()); + } + + let derived_ref = self.l1_fetcher + .l1_block_ref_by_number(derived_from.number) + .await?; + + if derived_ref.hash != derived_from.hash { + // self.emitter.emit(Event::Reset(ResetEvent { + // err: format!( + // "need to reset, we are on {:?}, not on the finalizing L1 chain {:?}", + // derived_from, + // derived_ref + // ) + // })).await; + return Err("Chain reset needed".into()); + } + + Ok::<(), Box>(()) + }).await; + + // match ctx { + // Ok(Ok(())) => { + // self.emitter.emit(Event::ForkchoiceUpdate(ForkchoiceUpdateEvent { + // finalized_l2_head: finalized_l2 + // })).await; + // } + // Ok(Err(e)) => { + // error!("Error during finalization, error {:?}", e.to_string()); + // } + // Err(_) => { + // error!("Timeout during finalization"); + // } + // } + } + return Ok(()) + } + + async fn find_last_btc_finalized_l2_block( + &mut self, + fd_l2_block_number: u64, + finalized_l2_number: u64, + gadget_activated_timestamp: u64, + ) -> Result> { + let block_count = (fd_l2_block_number - finalized_l2_number) as usize; + let mut l2_blocks = HashMap::new(); + let mut query_blocks = Vec::new(); + let mut largest_non_activated_block = None; + + for i in 0..block_count { + let block_number = (i as u64) + finalized_l2_number + 1; + let l2_block = match self.l2_fetcher.l2_block_ref_by_number(block_number) { + Ok(block) => block, + Err(e) => { + self.emitter.emit(Event::CriticalError(CriticalErrorEvent { + err: format!( + "failed to check if block {} to {} is finalized on Babylon, could not fetch block {}: {}", + finalized_l2_number + 1, + fd_l2_block_number, + block_number, + e + ) + })).await; + return Ok(None); + } + }; + + l2_blocks.insert(block_number, l2_block.clone()); + + if l2_block.time < gadget_activated_timestamp { + largest_non_activated_block = Some(l2_block); + continue; + } + + query_blocks.push(Block { + block_height: l2_block.number, + block_hash: l2_block.hash.to_string(), + block_timestamp: l2_block.time, + }); + } + + if query_blocks.is_empty() { + return Ok(largest_non_activated_block); + } + + match self.babylon_finality_client + .query_block_range_babylon_finalized(query_blocks.as_slice()) + .await + { + Ok(last_finalized_block_number) => { + if let Some(number) = last_finalized_block_number { + return Ok(l2_blocks.get(&number).cloned()); + } + } + Err(e) => { + self.emitter.emit(Event::CriticalError(CriticalErrorEvent { + err: format!( + "failed to check if block {} to {} is finalized on Babylon: {}", + finalized_l2_number + 1, + fd_l2_block_number, + e + ) + })).await; + } + } + + Ok(largest_non_activated_block) + } + + async fn on_reset(&self) { + let mut finality_data = self.finality_data.lock().unwrap(); + finality_data.clear(); + *self.tried_finalize_at.lock().unwrap() = 0; + } + + async fn on_derived_safe_block(&self, l2_safe: L2BlockRef, derived_from: L1BlockRef) { + let mut finality_data = self.finality_data.lock().unwrap(); + + if finality_data.is_empty() || + finality_data.last().unwrap().l1_block.number < derived_from.number { + + if finality_data.len() as u64 >= self.finality_lookback { + finality_data.drain(0..1); + } + + finality_data.push(FinalityData { + l2_block: l2_safe.clone(), + l1_block: BlockID { + number: derived_from.number, + hash: derived_from.hash, + }, + }); + + debug!("extended finality-data last_l1 {:?}, last_l2 {:?}", finality_data.last().unwrap().l1_block, finality_data.last().unwrap().l2_block); + } else { + let last = finality_data.last_mut().unwrap(); + if last.l2_block != l2_safe { + last.l2_block = l2_safe; + debug!("updated finality-data last_l1 {:?}, last_l2 {:?}", last.l1_block, last.l2_block); + } + } + } +} + +// Default implementations +#[derive(Default)] +pub struct NoopEmitter; + +#[async_trait] +impl EventEmitter for NoopEmitter { + async fn emit(&self, _event: Event) {} +} + +// #[async_trait] +// pub trait FinalizerL1Interface: Send + Sync { +// async fn l1_block_ref_by_number(&self, number: u64) -> Result>; +// } + +#[derive(Clone, Debug, Default)] +pub struct FinalizerL1Mock { +} + +#[async_trait] +impl FinalizerL1Interface for FinalizerL1Mock { + async fn l1_block_ref_by_number(&self, number: u64) -> Result> { + // Implement your gRPC client initialization here + let mock = L1BlockRef::default(); + + Ok(mock) + } +} + diff --git a/crates/rooch-finality/src/finality/mod.rs b/crates/rooch-finality/src/finality/mod.rs new file mode 100644 index 0000000000..e50e51d738 --- /dev/null +++ b/crates/rooch-finality/src/finality/mod.rs @@ -0,0 +1,5 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +pub mod expected_clients; +pub mod finalizer; diff --git a/crates/rooch-finality/src/lib.rs b/crates/rooch-finality/src/lib.rs index fe9a7f7eb5..ab5a15db41 100644 --- a/crates/rooch-finality/src/lib.rs +++ b/crates/rooch-finality/src/lib.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 pub mod actor; +pub mod finality; pub mod messages; pub mod metrics; pub mod proto; diff --git a/crates/rooch-finality/src/messages.rs b/crates/rooch-finality/src/messages.rs index 0a11d670db..2fd34df508 100644 --- a/crates/rooch-finality/src/messages.rs +++ b/crates/rooch-finality/src/messages.rs @@ -3,62 +3,15 @@ use anyhow::Result; use coerce::actor::message::Message; -use moveos_types::h256::H256; -use rooch_types::{ - sequencer::SequencerInfo, - transaction::{LedgerTransaction, LedgerTxData}, -}; +use rooch_types::finality_block::Block; use serde::{Deserialize, Serialize}; -/// Transaction Sequence Message +/// Finality Message #[derive(Debug, Serialize, Deserialize)] -pub struct TransactionSequenceMessage { - pub tx: LedgerTxData, +pub struct FinalityMessage { + pub block: Block, } -impl Message for TransactionSequenceMessage { - type Result = Result; -} - -/// Get Transaction By Hash Message -#[derive(Debug, Serialize, Deserialize)] -pub struct GetTransactionByHashMessage { - pub hash: H256, -} - -impl Message for GetTransactionByHashMessage { - type Result = Result>; -} - -/// Get Transactions By Hash Message -#[derive(Debug, Serialize, Deserialize)] -pub struct GetTransactionsByHashMessage { - pub tx_hashes: Vec, -} - -impl Message for GetTransactionsByHashMessage { - type Result = Result>>; -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct GetTxHashsMessage { - pub tx_orders: Vec, -} - -impl Message for GetTxHashsMessage { - type Result = Result>>; -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct GetSequencerOrderMessage {} - -impl Message for GetSequencerOrderMessage { - type Result = Result; -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct GetSequencerInfoMessage {} - -impl Message for GetSequencerInfoMessage { - type Result = Result; +impl Message for FinalityMessage { + type Result = Result<()>; } diff --git a/crates/rooch-finality/src/metrics.rs b/crates/rooch-finality/src/metrics.rs index 33cae5be48..4e0eb93597 100644 --- a/crates/rooch-finality/src/metrics.rs +++ b/crates/rooch-finality/src/metrics.rs @@ -5,25 +5,25 @@ use metrics::metrics_util::LATENCY_SEC_BUCKETS; use prometheus::{register_histogram_vec_with_registry, HistogramVec, Registry}; #[derive(Debug)] -pub struct SequencerMetrics { - pub sequencer_sequence_latency_seconds: HistogramVec, - pub sequencer_sequence_bytes: HistogramVec, +pub struct FinalityMetrics { + pub finality_latency_seconds: HistogramVec, + pub finality_bytes: HistogramVec, } -impl SequencerMetrics { +impl FinalityMetrics { pub(crate) fn new(registry: &Registry) -> Self { - SequencerMetrics { - sequencer_sequence_latency_seconds: register_histogram_vec_with_registry!( - "sequencer_sequence_latency_seconds", - "Sequencer sequence latency in seconds", + FinalityMetrics { + finality_latency_seconds: register_histogram_vec_with_registry!( + "finality_latency_seconds", + "Finality sequence latency in seconds", &["fn_name"], LATENCY_SEC_BUCKETS.to_vec(), registry, ) .unwrap(), - sequencer_sequence_bytes: register_histogram_vec_with_registry!( - "sequencer_sequence_bytes", - "Sequencer sequence size in bytes", + finality_bytes: register_histogram_vec_with_registry!( + "finality_bytes", + "Finality sequence size in bytes", &["fn_name"], prometheus::exponential_buckets(1.0, 4.0, 15) .unwrap() diff --git a/crates/rooch-finality/src/proto/finalitygadget.pb.go b/crates/rooch-finality/src/proto/finalitygadget.pb.go deleted file mode 100644 index 9942553c9b..0000000000 --- a/crates/rooch-finality/src/proto/finalitygadget.pb.go +++ /dev/null @@ -1,861 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v4.25.3 -// source: proto/finalitygadget.proto - -package proto - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type BlockInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // block_hash is the hash of the block - BlockHash string `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // block_height is the height of the block - BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` - // block_timestamp is the unix timestamp of the block - BlockTimestamp uint64 `protobuf:"varint,3,opt,name=block_timestamp,json=blockTimestamp,proto3" json:"block_timestamp,omitempty"` -} - -func (x *BlockInfo) Reset() { - *x = BlockInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlockInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockInfo) ProtoMessage() {} - -func (x *BlockInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlockInfo.ProtoReflect.Descriptor instead. -func (*BlockInfo) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{0} -} - -func (x *BlockInfo) GetBlockHash() string { - if x != nil { - return x.BlockHash - } - return "" -} - -func (x *BlockInfo) GetBlockHeight() uint64 { - if x != nil { - return x.BlockHeight - } - return 0 -} - -func (x *BlockInfo) GetBlockTimestamp() uint64 { - if x != nil { - return x.BlockTimestamp - } - return 0 -} - -type QueryIsBlockBabylonFinalizedRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Block *BlockInfo `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` -} - -func (x *QueryIsBlockBabylonFinalizedRequest) Reset() { - *x = QueryIsBlockBabylonFinalizedRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryIsBlockBabylonFinalizedRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryIsBlockBabylonFinalizedRequest) ProtoMessage() {} - -func (x *QueryIsBlockBabylonFinalizedRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryIsBlockBabylonFinalizedRequest.ProtoReflect.Descriptor instead. -func (*QueryIsBlockBabylonFinalizedRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{1} -} - -func (x *QueryIsBlockBabylonFinalizedRequest) GetBlock() *BlockInfo { - if x != nil { - return x.Block - } - return nil -} - -type QueryBlockRangeBabylonFinalizedRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Blocks []*BlockInfo `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"` -} - -func (x *QueryBlockRangeBabylonFinalizedRequest) Reset() { - *x = QueryBlockRangeBabylonFinalizedRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryBlockRangeBabylonFinalizedRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryBlockRangeBabylonFinalizedRequest) ProtoMessage() {} - -func (x *QueryBlockRangeBabylonFinalizedRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryBlockRangeBabylonFinalizedRequest.ProtoReflect.Descriptor instead. -func (*QueryBlockRangeBabylonFinalizedRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{2} -} - -func (x *QueryBlockRangeBabylonFinalizedRequest) GetBlocks() []*BlockInfo { - if x != nil { - return x.Blocks - } - return nil -} - -type QueryBlockRangeBabylonFinalizedResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // last_finalized_block_height is the height of the last finalized block - LastFinalizedBlockHeight uint64 `protobuf:"varint,1,opt,name=last_finalized_block_height,json=lastFinalizedBlockHeight,proto3" json:"last_finalized_block_height,omitempty"` -} - -func (x *QueryBlockRangeBabylonFinalizedResponse) Reset() { - *x = QueryBlockRangeBabylonFinalizedResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryBlockRangeBabylonFinalizedResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryBlockRangeBabylonFinalizedResponse) ProtoMessage() {} - -func (x *QueryBlockRangeBabylonFinalizedResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryBlockRangeBabylonFinalizedResponse.ProtoReflect.Descriptor instead. -func (*QueryBlockRangeBabylonFinalizedResponse) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{3} -} - -func (x *QueryBlockRangeBabylonFinalizedResponse) GetLastFinalizedBlockHeight() uint64 { - if x != nil { - return x.LastFinalizedBlockHeight - } - return 0 -} - -type QueryBtcStakingActivatedTimestampRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *QueryBtcStakingActivatedTimestampRequest) Reset() { - *x = QueryBtcStakingActivatedTimestampRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryBtcStakingActivatedTimestampRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryBtcStakingActivatedTimestampRequest) ProtoMessage() {} - -func (x *QueryBtcStakingActivatedTimestampRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryBtcStakingActivatedTimestampRequest.ProtoReflect.Descriptor instead. -func (*QueryBtcStakingActivatedTimestampRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{4} -} - -type QueryBtcStakingActivatedTimestampResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // timestamp is the unix timestamp when BTC staking was activated - ActivatedTimestamp uint64 `protobuf:"varint,1,opt,name=activated_timestamp,json=activatedTimestamp,proto3" json:"activated_timestamp,omitempty"` -} - -func (x *QueryBtcStakingActivatedTimestampResponse) Reset() { - *x = QueryBtcStakingActivatedTimestampResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryBtcStakingActivatedTimestampResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryBtcStakingActivatedTimestampResponse) ProtoMessage() {} - -func (x *QueryBtcStakingActivatedTimestampResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryBtcStakingActivatedTimestampResponse.ProtoReflect.Descriptor instead. -func (*QueryBtcStakingActivatedTimestampResponse) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{5} -} - -func (x *QueryBtcStakingActivatedTimestampResponse) GetActivatedTimestamp() uint64 { - if x != nil { - return x.ActivatedTimestamp - } - return 0 -} - -type QueryIsBlockFinalizedByHeightRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // block_height is the height of the block - BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` -} - -func (x *QueryIsBlockFinalizedByHeightRequest) Reset() { - *x = QueryIsBlockFinalizedByHeightRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryIsBlockFinalizedByHeightRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryIsBlockFinalizedByHeightRequest) ProtoMessage() {} - -func (x *QueryIsBlockFinalizedByHeightRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryIsBlockFinalizedByHeightRequest.ProtoReflect.Descriptor instead. -func (*QueryIsBlockFinalizedByHeightRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{6} -} - -func (x *QueryIsBlockFinalizedByHeightRequest) GetBlockHeight() uint64 { - if x != nil { - return x.BlockHeight - } - return 0 -} - -type QueryIsBlockFinalizedByHashRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // block_hash is the hash of the block - BlockHash string `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` -} - -func (x *QueryIsBlockFinalizedByHashRequest) Reset() { - *x = QueryIsBlockFinalizedByHashRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryIsBlockFinalizedByHashRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryIsBlockFinalizedByHashRequest) ProtoMessage() {} - -func (x *QueryIsBlockFinalizedByHashRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryIsBlockFinalizedByHashRequest.ProtoReflect.Descriptor instead. -func (*QueryIsBlockFinalizedByHashRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{7} -} - -func (x *QueryIsBlockFinalizedByHashRequest) GetBlockHash() string { - if x != nil { - return x.BlockHash - } - return "" -} - -type QueryIsBlockFinalizedResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // is_finalized is true if the block is finalized - IsFinalized bool `protobuf:"varint,1,opt,name=is_finalized,json=isFinalized,proto3" json:"is_finalized,omitempty"` -} - -func (x *QueryIsBlockFinalizedResponse) Reset() { - *x = QueryIsBlockFinalizedResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryIsBlockFinalizedResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryIsBlockFinalizedResponse) ProtoMessage() {} - -func (x *QueryIsBlockFinalizedResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryIsBlockFinalizedResponse.ProtoReflect.Descriptor instead. -func (*QueryIsBlockFinalizedResponse) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{8} -} - -func (x *QueryIsBlockFinalizedResponse) GetIsFinalized() bool { - if x != nil { - return x.IsFinalized - } - return false -} - -type QueryLatestFinalizedBlockRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *QueryLatestFinalizedBlockRequest) Reset() { - *x = QueryLatestFinalizedBlockRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryLatestFinalizedBlockRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryLatestFinalizedBlockRequest) ProtoMessage() {} - -func (x *QueryLatestFinalizedBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryLatestFinalizedBlockRequest.ProtoReflect.Descriptor instead. -func (*QueryLatestFinalizedBlockRequest) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{9} -} - -type QueryBlockResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Block *BlockInfo `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` -} - -func (x *QueryBlockResponse) Reset() { - *x = QueryBlockResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_finalitygadget_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryBlockResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryBlockResponse) ProtoMessage() {} - -func (x *QueryBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_finalitygadget_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryBlockResponse.ProtoReflect.Descriptor instead. -func (*QueryBlockResponse) Descriptor() ([]byte, []int) { - return file_proto_finalitygadget_proto_rawDescGZIP(), []int{10} -} - -func (x *QueryBlockResponse) GetBlock() *BlockInfo { - if x != nil { - return x.Block - } - return nil -} - -var File_proto_finalitygadget_proto protoreflect.FileDescriptor - -var file_proto_finalitygadget_proto_rawDesc = []byte{ - 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x67, 0x61, 0x64, 0x67, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x76, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x4d, 0x0a, 0x23, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x61, 0x62, 0x79, 0x6c, - 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x26, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0a, 0x26, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x61, 0x62, - 0x79, 0x6c, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x68, - 0x0a, 0x27, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x42, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, - 0x6c, 0x61, 0x73, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x2a, 0x0a, 0x28, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x42, 0x74, 0x63, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x5c, 0x0a, 0x29, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x74, 0x63, - 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x22, 0x49, 0x0a, 0x24, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x79, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x43, 0x0a, - 0x22, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x79, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, - 0x73, 0x68, 0x22, 0x42, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x22, 0x0a, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3c, 0x0a, 0x12, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x26, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x32, 0xd3, 0x05, 0x0a, 0x0e, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x61, 0x64, 0x67, 0x65, 0x74, 0x12, 0x70, 0x0a, 0x1c, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x61, 0x62, 0x79, 0x6c, - 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x2a, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x42, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, - 0x0a, 0x1f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x42, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x46, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x86, 0x01, 0x0a, 0x21, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x74, 0x63, 0x53, 0x74, 0x61, - 0x6b, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x42, 0x74, 0x63, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x74, 0x63, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x1d, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x64, 0x42, 0x79, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x79, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, - 0x1b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x79, 0x48, 0x61, 0x73, 0x68, 0x12, 0x29, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x79, 0x48, 0x61, 0x73, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, - 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x31, - 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, - 0x79, 0x6c, 0x6f, 0x6e, 0x6c, 0x61, 0x62, 0x73, 0x2d, 0x69, 0x6f, 0x2f, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x67, 0x61, 0x64, 0x67, 0x65, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_finalitygadget_proto_rawDescOnce sync.Once - file_proto_finalitygadget_proto_rawDescData = file_proto_finalitygadget_proto_rawDesc -) - -func file_proto_finalitygadget_proto_rawDescGZIP() []byte { - file_proto_finalitygadget_proto_rawDescOnce.Do(func() { - file_proto_finalitygadget_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_finalitygadget_proto_rawDescData) - }) - return file_proto_finalitygadget_proto_rawDescData -} - -var file_proto_finalitygadget_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_proto_finalitygadget_proto_goTypes = []interface{}{ - (*BlockInfo)(nil), // 0: proto.BlockInfo - (*QueryIsBlockBabylonFinalizedRequest)(nil), // 1: proto.QueryIsBlockBabylonFinalizedRequest - (*QueryBlockRangeBabylonFinalizedRequest)(nil), // 2: proto.QueryBlockRangeBabylonFinalizedRequest - (*QueryBlockRangeBabylonFinalizedResponse)(nil), // 3: proto.QueryBlockRangeBabylonFinalizedResponse - (*QueryBtcStakingActivatedTimestampRequest)(nil), // 4: proto.QueryBtcStakingActivatedTimestampRequest - (*QueryBtcStakingActivatedTimestampResponse)(nil), // 5: proto.QueryBtcStakingActivatedTimestampResponse - (*QueryIsBlockFinalizedByHeightRequest)(nil), // 6: proto.QueryIsBlockFinalizedByHeightRequest - (*QueryIsBlockFinalizedByHashRequest)(nil), // 7: proto.QueryIsBlockFinalizedByHashRequest - (*QueryIsBlockFinalizedResponse)(nil), // 8: proto.QueryIsBlockFinalizedResponse - (*QueryLatestFinalizedBlockRequest)(nil), // 9: proto.QueryLatestFinalizedBlockRequest - (*QueryBlockResponse)(nil), // 10: proto.QueryBlockResponse -} -var file_proto_finalitygadget_proto_depIdxs = []int32{ - 0, // 0: proto.QueryIsBlockBabylonFinalizedRequest.block:type_name -> proto.BlockInfo - 0, // 1: proto.QueryBlockRangeBabylonFinalizedRequest.blocks:type_name -> proto.BlockInfo - 0, // 2: proto.QueryBlockResponse.block:type_name -> proto.BlockInfo - 1, // 3: proto.FinalityGadget.QueryIsBlockBabylonFinalized:input_type -> proto.QueryIsBlockBabylonFinalizedRequest - 2, // 4: proto.FinalityGadget.QueryBlockRangeBabylonFinalized:input_type -> proto.QueryBlockRangeBabylonFinalizedRequest - 4, // 5: proto.FinalityGadget.QueryBtcStakingActivatedTimestamp:input_type -> proto.QueryBtcStakingActivatedTimestampRequest - 6, // 6: proto.FinalityGadget.QueryIsBlockFinalizedByHeight:input_type -> proto.QueryIsBlockFinalizedByHeightRequest - 7, // 7: proto.FinalityGadget.QueryIsBlockFinalizedByHash:input_type -> proto.QueryIsBlockFinalizedByHashRequest - 9, // 8: proto.FinalityGadget.QueryLatestFinalizedBlock:input_type -> proto.QueryLatestFinalizedBlockRequest - 8, // 9: proto.FinalityGadget.QueryIsBlockBabylonFinalized:output_type -> proto.QueryIsBlockFinalizedResponse - 3, // 10: proto.FinalityGadget.QueryBlockRangeBabylonFinalized:output_type -> proto.QueryBlockRangeBabylonFinalizedResponse - 5, // 11: proto.FinalityGadget.QueryBtcStakingActivatedTimestamp:output_type -> proto.QueryBtcStakingActivatedTimestampResponse - 8, // 12: proto.FinalityGadget.QueryIsBlockFinalizedByHeight:output_type -> proto.QueryIsBlockFinalizedResponse - 8, // 13: proto.FinalityGadget.QueryIsBlockFinalizedByHash:output_type -> proto.QueryIsBlockFinalizedResponse - 10, // 14: proto.FinalityGadget.QueryLatestFinalizedBlock:output_type -> proto.QueryBlockResponse - 9, // [9:15] is the sub-list for method output_type - 3, // [3:9] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_proto_finalitygadget_proto_init() } -func file_proto_finalitygadget_proto_init() { - if File_proto_finalitygadget_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_finalitygadget_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlockInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryIsBlockBabylonFinalizedRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryBlockRangeBabylonFinalizedRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryBlockRangeBabylonFinalizedResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryBtcStakingActivatedTimestampRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryBtcStakingActivatedTimestampResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryIsBlockFinalizedByHeightRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryIsBlockFinalizedByHashRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryIsBlockFinalizedResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryLatestFinalizedBlockRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_finalitygadget_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryBlockResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_finalitygadget_proto_rawDesc, - NumEnums: 0, - NumMessages: 11, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_proto_finalitygadget_proto_goTypes, - DependencyIndexes: file_proto_finalitygadget_proto_depIdxs, - MessageInfos: file_proto_finalitygadget_proto_msgTypes, - }.Build() - File_proto_finalitygadget_proto = out.File - file_proto_finalitygadget_proto_rawDesc = nil - file_proto_finalitygadget_proto_goTypes = nil - file_proto_finalitygadget_proto_depIdxs = nil -} diff --git a/crates/rooch-finality/src/proto/mod.rs b/crates/rooch-finality/src/proto/mod.rs index ce4df98921..d711e6e513 100644 --- a/crates/rooch-finality/src/proto/mod.rs +++ b/crates/rooch-finality/src/proto/mod.rs @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + // This file is @generated by prost-build. pub mod proto { include!("proto.rs"); diff --git a/crates/rooch-finality/src/proxy/mod.rs b/crates/rooch-finality/src/proxy/mod.rs index c60b96a6c6..521ad1427d 100644 --- a/crates/rooch-finality/src/proxy/mod.rs +++ b/crates/rooch-finality/src/proxy/mod.rs @@ -1,55 +1,23 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use crate::messages::{ - GetSequencerInfoMessage, GetSequencerOrderMessage, GetTransactionByHashMessage, - GetTransactionsByHashMessage, GetTxHashsMessage, -}; -use crate::{actor::sequencer::SequencerActor, messages::TransactionSequenceMessage}; +use crate::actor::finality::FinalityActor; +use crate::messages::FinalityMessage; use anyhow::Result; use coerce::actor::ActorRef; -use moveos_types::h256::H256; -use rooch_types::sequencer::SequencerInfo; -use rooch_types::transaction::{LedgerTransaction, LedgerTxData}; +use rooch_types::finality_block::Block; #[derive(Clone)] -pub struct SequencerProxy { - pub actor: ActorRef, +pub struct FinalityProxy { + pub actor: ActorRef, } -impl SequencerProxy { - pub fn new(actor: ActorRef) -> Self { +impl FinalityProxy { + pub fn new(actor: ActorRef) -> Self { Self { actor } } - pub async fn sequence_transaction(&self, tx: LedgerTxData) -> Result { - self.actor.send(TransactionSequenceMessage { tx }).await? - } - - pub async fn get_transaction_by_hash(&self, hash: H256) -> Result> { - self.actor - .send(GetTransactionByHashMessage { hash }) - .await? - } - - pub async fn get_transactions_by_hash( - &self, - tx_hashes: Vec, - ) -> Result>> { - self.actor - .send(GetTransactionsByHashMessage { tx_hashes }) - .await? - } - - pub async fn get_tx_hashes(&self, tx_orders: Vec) -> Result>> { - self.actor.send(GetTxHashsMessage { tx_orders }).await? - } - - pub async fn get_sequencer_order(&self) -> Result { - self.actor.send(GetSequencerOrderMessage {}).await? - } - - pub async fn get_sequencer_info(&self) -> Result { - self.actor.send(GetSequencerInfoMessage {}).await? + pub async fn finality(&self, block: Block) -> Result<()> { + self.actor.send(FinalityMessage { block }).await? } } diff --git a/crates/rooch-finality/src/rpc_client.rs b/crates/rooch-finality/src/rpc_client.rs index 53b5ea1358..a226217c83 100644 --- a/crates/rooch-finality/src/rpc_client.rs +++ b/crates/rooch-finality/src/rpc_client.rs @@ -10,8 +10,8 @@ use crate::proto::proto::{ QueryIsBlockBabylonFinalizedRequest, QueryIsBlockFinalizedByHashRequest, QueryIsBlockFinalizedByHeightRequest, QueryLatestFinalizedBlockRequest, }; -use crate::types::block::Block; -use prost::Message; +use anyhow::Result; +use rooch_types::finality_block::Block; pub struct FinalityGadgetGrpcClient { client: FinalityGadgetClient, @@ -19,16 +19,17 @@ pub struct FinalityGadgetGrpcClient { impl FinalityGadgetGrpcClient { pub async fn new(remote_addr: String) -> Result> { - let channel = Channel::from_shared(remote_addr)? - .connect() - .await?; + let channel = Channel::from_shared(remote_addr)?.connect().await?; let client = FinalityGadgetClient::new(channel); Ok(Self { client }) } - pub async fn query_is_block_babylon_finalized(&mut self, block: &Block) -> Result> { + pub async fn query_is_block_babylon_finalized( + &mut self, + block: &Block, + ) -> Result> { let req = Request::new(QueryIsBlockBabylonFinalizedRequest { block: Some(BlockInfo { block_hash: block.block_hash.clone(), @@ -71,11 +72,17 @@ impl FinalityGadgetGrpcClient { pub async fn query_btc_staking_activated_timestamp(&mut self) -> Result> { let req = Request::new(QueryBtcStakingActivatedTimestampRequest {}); - let response = self.client.query_btc_staking_activated_timestamp(req).await?; + let response = self + .client + .query_btc_staking_activated_timestamp(req) + .await?; Ok(response.into_inner().activated_timestamp) } - pub async fn query_is_block_finalized_by_height(&mut self, height: u64) -> Result> { + pub async fn query_is_block_finalized_by_height( + &mut self, + height: u64, + ) -> Result> { let req = Request::new(QueryIsBlockFinalizedByHeightRequest { block_height: height, }); @@ -84,10 +91,11 @@ impl FinalityGadgetGrpcClient { Ok(response.into_inner().is_finalized) } - pub async fn query_is_block_finalized_by_hash(&mut self, hash: String) -> Result> { - let req = Request::new(QueryIsBlockFinalizedByHashRequest { - block_hash: hash, - }); + pub async fn query_is_block_finalized_by_hash( + &mut self, + hash: String, + ) -> Result> { + let req = Request::new(QueryIsBlockFinalizedByHashRequest { block_hash: hash }); let response = self.client.query_is_block_finalized_by_hash(req).await?; Ok(response.into_inner().is_finalized) @@ -111,4 +119,4 @@ impl Drop for FinalityGadgetGrpcClient { fn drop(&mut self) { // Channel cleanup is handled automatically by tonic } -} \ No newline at end of file +} diff --git a/crates/rooch-finality/src/types/block.go b/crates/rooch-finality/src/types/block.go deleted file mode 100644 index 4a9b218994..0000000000 --- a/crates/rooch-finality/src/types/block.go +++ /dev/null @@ -1,14 +0,0 @@ -package types - -type Block struct { - BlockHash string `json:"block_hash" description:"block hash"` - BlockHeight uint64 `json:"block_height" description:"block height"` - BlockTimestamp uint64 `json:"block_timestamp" description:"block timestamp"` -} - -type ChainSyncStatus struct { - LatestBlockHeight uint64 `json:"latest_block"` - LatestBtcFinalizedBlockHeight uint64 `json:"latest_btc_finalized_block"` - EarliestBtcFinalizedBlockHeight uint64 `json:"earliest_btc_finalized_block"` - LatestEthFinalizedBlockHeight uint64 `json:"latest_eth_finalized_block"` -} diff --git a/crates/rooch-finality/src/types/errors.go b/crates/rooch-finality/src/types/errors.go deleted file mode 100644 index f7a919718e..0000000000 --- a/crates/rooch-finality/src/types/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package types - -import "errors" - -var ( - ErrBlockNotFound = errors.New("block not found") - ErrNoFpHasVotingPower = errors.New("no FP has voting power for the consumer chain") - ErrBtcStakingNotActivated = errors.New("BTC staking is not activated for the consumer chain") - ErrActivatedTimestampNotFound = errors.New("BTC staking activated timestamp not found") -) diff --git a/crates/rooch-finality/src/types/errors.rs b/crates/rooch-finality/src/types/errors.rs index 2e7ee48c95..53469f0102 100644 --- a/crates/rooch-finality/src/types/errors.rs +++ b/crates/rooch-finality/src/types/errors.rs @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("block not found")] diff --git a/crates/rooch-finality/src/types/mod.rs b/crates/rooch-finality/src/types/mod.rs index 0ae16937c1..b7ba5e7ffd 100644 --- a/crates/rooch-finality/src/types/mod.rs +++ b/crates/rooch-finality/src/types/mod.rs @@ -1,5 +1,5 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -pub mod block; + pub mod errors; pub mod transaction; diff --git a/crates/rooch-finality/src/types/transaction.go b/crates/rooch-finality/src/types/transaction.go deleted file mode 100644 index e24f8c258c..0000000000 --- a/crates/rooch-finality/src/types/transaction.go +++ /dev/null @@ -1,20 +0,0 @@ -package types - -type TransactionInfo struct { - TxHash string `json:"txHash"` - BlockHash string `json:"blockHash"` - Status FinalityStatus `json:"status"` - BlockTimestamp uint64 `json:"blockTimestamp"` - BlockHeight uint64 `json:"blockHeight"` - BabylonFinalized bool `json:"babylonFinalized"` -} - -type FinalityStatus string - -const ( - FinalityStatusPending FinalityStatus = "pending" - FinalityStatusUnsafe FinalityStatus = "unsafe" - FinalityStatusBitcoinFinalized FinalityStatus = "btc finalized" - FinalityStatusSafe FinalityStatus = "safe" - FinalityStatusFinalized FinalityStatus = "finalized" -) diff --git a/crates/rooch-finality/src/types/transaction.rs b/crates/rooch-finality/src/types/transaction.rs index 5580cd49e7..d1c7aaf045 100644 --- a/crates/rooch-finality/src/types/transaction.rs +++ b/crates/rooch-finality/src/types/transaction.rs @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] diff --git a/crates/rooch-finality/tests/test_sequencer.rs b/crates/rooch-finality/tests/test_sequencer.rs deleted file mode 100644 index a39d3a2454..0000000000 --- a/crates/rooch-finality/tests/test_sequencer.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) RoochNetwork -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::Result; -use coerce::actor::{system::ActorSystem, IntoActor}; -use metrics::RegistryService; -use prometheus::Registry; -use raw_store::metrics::DBMetrics; -use raw_store::{StoreInstance, CF_METRICS_REPORT_PERIOD_MILLIS}; -use rooch_config::RoochOpt; -use rooch_db::RoochDB; -use rooch_genesis::RoochGenesis; -use rooch_sequencer::{actor::sequencer::SequencerActor, proxy::SequencerProxy}; -use rooch_types::{ - crypto::RoochKeyPair, - service_status::ServiceStatus, - transaction::{LedgerTxData, RoochTransaction}, -}; -use std::time::Duration; - -fn init_rooch_db(opt: &RoochOpt, registry: &Registry) -> Result { - DBMetrics::init(registry); - let store_instance = RoochDB::generate_store_instance(opt.store_config(), registry)?; - init_rooch_db_with_instance(opt, store_instance, registry) -} - -fn init_rooch_db_with_instance( - opt: &RoochOpt, - instance: StoreInstance, - registry: &Registry, -) -> Result { - let rooch_db = RoochDB::init_with_instance(opt.store_config(), instance, registry)?; - let network = opt.network(); - let _genesis = RoochGenesis::load_or_init(network, &rooch_db)?; - Ok(rooch_db) -} - -#[tokio::test] -async fn test_sequencer() -> Result<()> { - let opt = RoochOpt::new_with_temp_store()?; - let mut last_tx_order = 0; - let registry_service = RegistryService::default(); - { - let mut store_instance = RoochDB::generate_store_instance( - opt.store_config(), - ®istry_service.default_registry(), - )?; - let rooch_db = init_rooch_db_with_instance( - &opt, - store_instance.clone(), - ®istry_service.default_registry(), - )?; - let sequencer_key = RoochKeyPair::generate_secp256k1(); - let mut sequencer = SequencerActor::new( - sequencer_key, - rooch_db.rooch_store, - ServiceStatus::Active, - ®istry_service.default_registry(), - None, - )?; - assert_eq!(sequencer.last_order(), last_tx_order); - for _ in 0..10 { - let tx_data = LedgerTxData::L2Tx(RoochTransaction::mock()); - let ledger_tx = sequencer.sequence(tx_data)?; - assert_eq!(ledger_tx.sequence_info.tx_order, last_tx_order + 1); - last_tx_order = ledger_tx.sequence_info.tx_order; - } - assert_eq!(sequencer.last_order(), last_tx_order); - - let _ = store_instance.cancel_metrics_task(); - // Wait for rocksdb cancel metrics task to avoid db lock - tokio::time::sleep(Duration::from_millis(CF_METRICS_REPORT_PERIOD_MILLIS)).await; - } - // load from db again - { - // To aviod AlreadyReg for re init the same db - let new_registry = prometheus::Registry::new(); - let rooch_db = RoochDB::init(opt.store_config(), &new_registry)?; - let sequencer_key = RoochKeyPair::generate_secp256k1(); - let mut sequencer = SequencerActor::new( - sequencer_key, - rooch_db.rooch_store, - ServiceStatus::Active, - &new_registry, - None, - )?; - assert_eq!(sequencer.last_order(), last_tx_order); - let tx_data = LedgerTxData::L2Tx(RoochTransaction::mock()); - let ledger_tx = sequencer.sequence(tx_data)?; - assert_eq!(ledger_tx.sequence_info.tx_order, last_tx_order + 1); - } - Ok(()) -} - -// test concurrent -// Build a sequencer actor and sequence transactions concurrently -#[tokio::test(flavor = "multi_thread", worker_threads = 5)] -async fn test_sequencer_concurrent() -> Result<()> { - let opt = RoochOpt::new_with_temp_store()?; - let registry_service = RegistryService::default(); - let rooch_db = init_rooch_db(&opt, ®istry_service.default_registry())?; - let sequencer_key = RoochKeyPair::generate_secp256k1(); - - let actor_system = ActorSystem::global_system(); - - let sequencer = SequencerActor::new( - sequencer_key, - rooch_db.rooch_store, - ServiceStatus::Active, - ®istry_service.default_registry(), - None, - )? - .into_actor(Some("Sequencer"), &actor_system) - .await?; - let sequencer_proxy = SequencerProxy::new(sequencer.into()); - - // start n thread to sequence - let n = 10; - let mut handles = vec![]; - for _ in 0..n { - let sequencer_proxy = sequencer_proxy.clone(); - //Use tokio to spawn a new async task - let handle = tokio::task::spawn(async move { - for _ in 0..n { - let tx_data = LedgerTxData::L2Tx(RoochTransaction::mock()); - let _ = sequencer_proxy.sequence_transaction(tx_data).await.unwrap(); - } - }); - handles.push(handle); - } - for handle in handles { - handle.await?; - } - - let sequencer_order = sequencer_proxy.get_sequencer_order().await?; - assert_eq!(sequencer_order, n * n); - - Ok(()) -} diff --git a/crates/rooch-open-rpc-spec/schemas/openrpc.json b/crates/rooch-open-rpc-spec/schemas/openrpc.json index abc6d7a470..6e3555060a 100644 --- a/crates/rooch-open-rpc-spec/schemas/openrpc.json +++ b/crates/rooch-open-rpc-spec/schemas/openrpc.json @@ -3014,6 +3014,13 @@ "enum": [ "date-import-mode" ] + }, + { + "description": "The service is in finality mode.", + "type": "string", + "enum": [ + "finality-mode" + ] } ] }, diff --git a/crates/rooch-finality/src/types/block.rs b/crates/rooch-types/src/finality_block.rs similarity index 57% rename from crates/rooch-finality/src/types/block.rs rename to crates/rooch-types/src/finality_block.rs index e116553c0d..16f3f70402 100644 --- a/crates/rooch-finality/src/types/block.rs +++ b/crates/rooch-types/src/finality_block.rs @@ -1,3 +1,7 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use moveos_types::h256::H256; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -10,6 +14,29 @@ pub struct Block { pub block_timestamp: u64, } +// Types and Structs +#[derive(Clone, Debug, Default, PartialEq)] +pub struct BlockID { + pub number: u64, + pub hash: String, +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub struct L1BlockRef { + pub hash: String, + pub number: u64, + pub time: u64, + pub parent_hash: String, +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub struct L2BlockRef { + pub hash: H256, + pub number: u64, + pub time: u64, + pub parent_hash: H256, +} + #[derive(Debug, Serialize, Deserialize)] pub struct ChainSyncStatus { #[serde(rename = "latest_block")] @@ -20,4 +47,4 @@ pub struct ChainSyncStatus { pub earliest_btc_finalized_block_height: u64, #[serde(rename = "latest_eth_finalized_block")] pub latest_eth_finalized_block_height: u64, -} \ No newline at end of file +} diff --git a/crates/rooch-types/src/lib.rs b/crates/rooch-types/src/lib.rs index 6612bd4aeb..38a09a09a4 100644 --- a/crates/rooch-types/src/lib.rs +++ b/crates/rooch-types/src/lib.rs @@ -29,4 +29,5 @@ pub mod test_utils; pub mod to_bech32; pub mod transaction; +pub mod finality_block; pub mod service_type; diff --git a/crates/rooch-types/src/service_status.rs b/crates/rooch-types/src/service_status.rs index 2fc5a08aeb..f7ded63352 100644 --- a/crates/rooch-types/src/service_status.rs +++ b/crates/rooch-types/src/service_status.rs @@ -18,6 +18,8 @@ pub enum ServiceStatus { ReadOnlyMode, /// The service is in date import mode. DateImportMode, + /// The service is in finality mode. + FinalityMode, } impl ServiceStatus { @@ -36,4 +38,7 @@ impl ServiceStatus { pub fn is_date_import_mode(&self) -> bool { matches!(self, ServiceStatus::DateImportMode) } + pub fn is_finality_mode(&self) -> bool { + matches!(self, ServiceStatus::FinalityMode) + } }