diff --git a/sequencer_core/src/block_settlement_client.rs b/sequencer_core/src/block_settlement_client.rs index e3badf2d..16afa9c1 100644 --- a/sequencer_core/src/block_settlement_client.rs +++ b/sequencer_core/src/block_settlement_client.rs @@ -23,7 +23,7 @@ pub trait BlockSettlementClientTrait: Clone { fn bedrock_signing_key(&self) -> &Ed25519Key; /// Post a transaction to the node. - async fn submit_block_to_bedrock(&self, block: &Block) -> Result; + async fn submit_inscribe_tx_to_bedrock(&self, tx: SignedMantleTx) -> Result<()>; /// Create and sign a transaction for inscribing data. fn create_inscribe_tx(&self, block: &Block) -> Result<(SignedMantleTx, MsgId)> { @@ -89,16 +89,13 @@ impl BlockSettlementClientTrait for BlockSettlementClient { }) } - async fn submit_block_to_bedrock(&self, block: &Block) -> Result { - let (tx, new_msg_id) = self.create_inscribe_tx(block)?; - - // Post the transaction + async fn submit_inscribe_tx_to_bedrock(&self, tx: SignedMantleTx) -> Result<()> { self.bedrock_client .post_transaction(tx) .await .context("Failed to post transaction to Bedrock")?; - Ok(new_msg_id) + Ok(()) } fn bedrock_channel_id(&self) -> ChannelId { diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 8d719d65..f9b8f661 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -167,14 +167,25 @@ impl SequencerCore Result { { - let block = self.produce_new_block_with_mempool_transactions()?; + let block = self + .produce_new_block_with_mempool_transactions() + .context("Failed to produce new block with mempool transactions")?; + let (tx, msg_id) = self + .block_settlement_client + .create_inscribe_tx(&block) + .with_context(|| { + format!( + "Failed to create inscribe transaction for block with id {}", + block.header.block_id + ) + })?; + self.last_bedrock_msg_id = msg_id.into(); match self .block_settlement_client - .submit_block_to_bedrock(&block) + .submit_inscribe_tx_to_bedrock(tx) .await { - Ok(msg_id) => { - self.last_bedrock_msg_id = msg_id.into(); + Ok(()) => { info!("Posted block data to Bedrock, msg_id: {msg_id:?}"); } Err(err) => { @@ -801,4 +812,35 @@ mod tests { assert_eq!(sequencer.get_pending_blocks().unwrap().len(), 1); } + + #[tokio::test] + async fn test_last_bedrock_msg_id_updated_even_when_posting_fails() { + use crate::mock::{MockBlockSettlementClientWithError, MockIndexerClient}; + + let config = setup_sequencer_config(); + let (mut sequencer, mempool_handle) = crate::SequencerCore::< + MockBlockSettlementClientWithError, + MockIndexerClient, + >::start_from_config(config) + .await; + + // Store the initial last_bedrock_msg_id (should be genesis parent msg id) + let initial_msg_id = sequencer.last_bedrock_msg_id; + assert_eq!(initial_msg_id, [0; 32]); + + // Add a transaction to the mempool + let tx = common::test_utils::produce_dummy_empty_transaction(); + mempool_handle.push(tx).await.unwrap(); + + // Produce a block and post to settlement layer (which will fail) + let result = sequencer + .produce_new_block_and_post_to_settlement_layer() + .await; + + // The method should succeed even though posting to Bedrock failed + assert!(result.is_ok()); + + // Verify that last_bedrock_msg_id was updated despite the posting failure + assert_ne!(sequencer.last_bedrock_msg_id, initial_msg_id); + } } diff --git a/sequencer_core/src/mock.rs b/sequencer_core/src/mock.rs index 16799d11..930ff946 100644 --- a/sequencer_core/src/mock.rs +++ b/sequencer_core/src/mock.rs @@ -1,6 +1,6 @@ -use anyhow::Result; -use common::block::Block; -use logos_blockchain_core::mantle::ops::channel::{ChannelId, MsgId}; +use anyhow::{Result, anyhow}; +use bedrock_client::SignedMantleTx; +use logos_blockchain_core::mantle::ops::channel::ChannelId; use logos_blockchain_key_management_system_service::keys::Ed25519Key; use url::Url; @@ -34,8 +34,35 @@ impl BlockSettlementClientTrait for MockBlockSettlementClient { &self.bedrock_signing_key } - async fn submit_block_to_bedrock(&self, block: &Block) -> Result { - self.create_inscribe_tx(block).map(|(_, msg_id)| msg_id) + async fn submit_inscribe_tx_to_bedrock(&self, _tx: SignedMantleTx) -> Result<()> { + Ok(()) + } +} + +#[derive(Clone)] +pub struct MockBlockSettlementClientWithError { + bedrock_channel_id: ChannelId, + bedrock_signing_key: Ed25519Key, +} + +impl BlockSettlementClientTrait for MockBlockSettlementClientWithError { + fn new(config: &BedrockConfig, bedrock_signing_key: Ed25519Key) -> Result { + Ok(Self { + bedrock_channel_id: config.channel_id, + bedrock_signing_key, + }) + } + + fn bedrock_channel_id(&self) -> ChannelId { + self.bedrock_channel_id + } + + fn bedrock_signing_key(&self) -> &Ed25519Key { + &self.bedrock_signing_key + } + + async fn submit_inscribe_tx_to_bedrock(&self, _tx: SignedMantleTx) -> Result<()> { + Err(anyhow!("Mock error")) } } diff --git a/sequencer_runner/src/lib.rs b/sequencer_runner/src/lib.rs index 1dab37d5..f6391af2 100644 --- a/sequencer_runner/src/lib.rs +++ b/sequencer_runner/src/lib.rs @@ -176,10 +176,19 @@ async fn retry_pending_blocks_loop( info!("Resubmitting {} pending blocks", pending_blocks.len()); for block in &pending_blocks { - if let Err(e) = block_settlement_client.submit_block_to_bedrock(block).await { + // TODO: We could cache the inscribe tx for each pending block to avoid re-creating it + // on every retry. + let (tx, _msg_id) = block_settlement_client + .create_inscribe_tx(block) + .context("Failed to create inscribe tx for pending block")?; + + if let Err(e) = block_settlement_client + .submit_inscribe_tx_to_bedrock(tx) + .await + { warn!( - "Failed to resubmit block with id {} with error {}", - block.header.block_id, e + "Failed to resubmit block with id {} with error {e:#}", + block.header.block_id ); } }