feat!(sequencer): add is_our_turn

This commit is contained in:
erhant 2026-07-09 18:06:08 +03:00
parent 1fa5cb795c
commit d90dbd83b2
4 changed files with 34 additions and 10 deletions

View File

@ -12,10 +12,14 @@ use logos_blockchain_zone_sdk::{
adapter::NodeHttpClient, adapter::NodeHttpClient,
sequencer::{ sequencer::{
DepositInfo, Event, FinalizedOp, InscriptionInfo, DepositInfo, Event, FinalizedOp, InscriptionInfo,
SequencerConfig as ZoneSdkSequencerConfig, WithdrawArg, WithdrawInfo, ZoneSequencer, SequencerConfig as ZoneSdkSequencerConfig, TurnNotification, WithdrawArg, WithdrawInfo,
ZoneSequencer,
}, },
}; };
use tokio::{sync::mpsc, task::JoinHandle}; use tokio::{
sync::{mpsc, watch},
task::JoinHandle,
};
use crate::config::BedrockConfig; use crate::config::BedrockConfig;
@ -63,6 +67,9 @@ pub trait BlockPublisherTrait: Clone {
async fn publish_block(&self, block: &Block, withdrawals: Vec<WithdrawArg>) -> Result<()>; async fn publish_block(&self, block: &Block, withdrawals: Vec<WithdrawArg>) -> Result<()>;
fn channel_id(&self) -> ChannelId; fn channel_id(&self) -> ChannelId;
/// Whether this sequencer is currently authorized to write to the channel.
fn is_our_turn(&self) -> bool;
} }
/// Real block publisher backed by zone-sdk's `ZoneSequencer`. /// Real block publisher backed by zone-sdk's `ZoneSequencer`.
@ -70,6 +77,7 @@ pub trait BlockPublisherTrait: Clone {
pub struct ZoneSdkPublisher { pub struct ZoneSdkPublisher {
channel_id: ChannelId, channel_id: ChannelId,
publish_tx: mpsc::Sender<(Inscription, Vec<WithdrawArg>)>, publish_tx: mpsc::Sender<(Inscription, Vec<WithdrawArg>)>,
turn_rx: watch::Receiver<TurnNotification>,
// Aborts the drive task when the last clone is dropped. // Aborts the drive task when the last clone is dropped.
_drive_task: Arc<DriveTaskGuard>, _drive_task: Arc<DriveTaskGuard>,
} }
@ -112,6 +120,8 @@ impl BlockPublisherTrait for ZoneSdkPublisher {
// Grab readiness receiver before moving the sequencer into the drive // Grab readiness receiver before moving the sequencer into the drive
// task so we can await cold-start completion below. // task so we can await cold-start completion below.
let mut ready_rx = sequencer.subscribe_ready(); let mut ready_rx = sequencer.subscribe_ready();
// Grab the turn watch before the move; the sdk actor keeps it current.
let turn_rx = sequencer.subscribe_turn_to_write();
let (publish_tx, mut publish_rx) = let (publish_tx, mut publish_rx) =
mpsc::channel::<(Inscription, Vec<WithdrawArg>)>(PUBLISH_INBOX_CAPACITY); mpsc::channel::<(Inscription, Vec<WithdrawArg>)>(PUBLISH_INBOX_CAPACITY);
@ -197,6 +207,7 @@ impl BlockPublisherTrait for ZoneSdkPublisher {
Ok(Self { Ok(Self {
channel_id: config.channel_id, channel_id: config.channel_id,
publish_tx, publish_tx,
turn_rx,
_drive_task: Arc::new(DriveTaskGuard(drive_task)), _drive_task: Arc::new(DriveTaskGuard(drive_task)),
}) })
} }
@ -218,6 +229,10 @@ impl BlockPublisherTrait for ZoneSdkPublisher {
fn channel_id(&self) -> ChannelId { fn channel_id(&self) -> ChannelId {
self.channel_id self.channel_id
} }
fn is_our_turn(&self) -> bool {
self.turn_rx.borrow().our_turn_to_write
}
} }
/// Deserialize inscription payload as a `Block` and return it's`block_id`. /// Deserialize inscription payload as a `Block` and return it's`block_id`.

View File

@ -534,6 +534,12 @@ impl<BP: BlockPublisherTrait> SequencerCore<BP> {
self.block_publisher.clone() self.block_publisher.clone()
} }
/// Whether this sequencer is currently authorized to write to the channel.
#[must_use]
pub fn is_our_turn(&self) -> bool {
self.block_publisher.is_our_turn()
}
fn next_block_id(&self) -> u64 { fn next_block_id(&self) -> u64 {
self.chain_height self.chain_height
.checked_add(1) .checked_add(1)

View File

@ -48,4 +48,8 @@ impl BlockPublisherTrait for MockBlockPublisher {
fn channel_id(&self) -> ChannelId { fn channel_id(&self) -> ChannelId {
self.channel_id self.channel_id
} }
fn is_our_turn(&self) -> bool {
true
}
} }

View File

@ -172,16 +172,15 @@ async fn main_loop(seq_core: Arc<Mutex<SequencerCore>>, block_timeout: Duration)
loop { loop {
tokio::time::sleep(block_timeout).await; tokio::time::sleep(block_timeout).await;
info!("Collecting transactions from mempool, block creation"); let mut state = seq_core.lock().await;
let id = { // Only produce on our turn.
let mut state = seq_core.lock().await; if !state.is_our_turn() {
continue;
state.produce_new_block().await? }
};
info!("Our turn: collecting transactions from mempool, creating block");
let id = state.produce_new_block().await?;
info!("Block with id {id} created"); info!("Block with id {id} created");
info!("Waiting for new transactions");
} }
} }