diff --git a/sequencer/src/context.rs b/sequencer/src/context.rs index 2b51b8989..2875df16c 100644 --- a/sequencer/src/context.rs +++ b/sequencer/src/context.rs @@ -533,9 +533,8 @@ async fn fetch_proposal_chain( async fn load_anchor_view(persistence: &impl SequencerPersistence) -> ViewNumber { loop { - match persistence.load_anchor_leaf().await { - Ok(Some((leaf, _))) => break leaf.view_number(), - Ok(None) => break ViewNumber::genesis(), + match persistence.load_anchor_view().await { + Ok(view) => break view, Err(err) => { tracing::warn!("error loading anchor view: {err:#}"); sleep(Duration::from_secs(1)).await; diff --git a/sequencer/src/persistence.rs b/sequencer/src/persistence.rs index 69266db6f..457717683 100644 --- a/sequencer/src/persistence.rs +++ b/sequencer/src/persistence.rs @@ -365,6 +365,11 @@ mod persistence_tests { final_qc, ]; + assert_eq!( + storage.load_anchor_view().await.unwrap(), + ViewNumber::genesis() + ); + let consumer = EventCollector::default(); let leaf_chain = leaves .iter() @@ -381,6 +386,10 @@ mod persistence_tests { ) .await .unwrap(); + assert_eq!( + storage.load_anchor_view().await.unwrap(), + ViewNumber::new(2) + ); for i in 0..=2 { assert_eq!( @@ -430,6 +439,10 @@ mod persistence_tests { storage.load_anchor_leaf().await.unwrap(), Some((leaves[2].clone(), qcs[2].clone())) ); + assert_eq!( + storage.load_anchor_view().await.unwrap(), + leaves[2].view_number() + ); // Process a second decide event. let consumer = EventCollector::default(); @@ -442,6 +455,10 @@ mod persistence_tests { ) .await .unwrap(); + assert_eq!( + storage.load_anchor_view().await.unwrap(), + ViewNumber::new(3) + ); // A decide event should have been processed. let events = consumer.events.read().await; @@ -643,6 +660,10 @@ mod persistence_tests { .view_number(), ViewNumber::new(1) ); + assert_eq!( + storage.load_anchor_view().await.unwrap(), + ViewNumber::new(1) + ); // Now decide remaining leaves successfully. We should now garbage collect and process a // decide event for all the leaves. @@ -686,6 +707,10 @@ mod persistence_tests { .view_number(), ViewNumber::new(3) ); + assert_eq!( + storage.load_anchor_view().await.unwrap(), + ViewNumber::new(3) + ); // Check decide event. tracing::info!("check decide event"); diff --git a/sequencer/src/persistence/sql.rs b/sequencer/src/persistence/sql.rs index 71136343d..ff0d9d04c 100644 --- a/sequencer/src/persistence/sql.rs +++ b/sequencer/src/persistence/sql.rs @@ -401,6 +401,14 @@ impl SequencerPersistence for Persistence { Ok(Some((leaf, qc))) } + async fn load_anchor_view(&self) -> anyhow::Result { + let mut tx = self.db.read().await?; + let (view,) = query_as::<(i64,)>("SELECT coalesce(max(view), 0) FROM anchor_leaf") + .fetch_one(tx.as_mut()) + .await?; + Ok(ViewNumber::new(view as u64)) + } + async fn load_undecided_state( &self, ) -> anyhow::Result, BTreeMap>)>> { diff --git a/types/src/v0/traits.rs b/types/src/v0/traits.rs index 32bc3aa09..e8ee45a3a 100644 --- a/types/src/v0/traits.rs +++ b/types/src/v0/traits.rs @@ -603,6 +603,13 @@ pub trait SequencerPersistence: Sized + Send + Sync + 'static { &self, decided_upgrade_certificate: Option>, ) -> anyhow::Result<()>; + + async fn load_anchor_view(&self) -> anyhow::Result { + match self.load_anchor_leaf().await? { + Some((leaf, _)) => Ok(leaf.view_number()), + None => Ok(ViewNumber::genesis()), + } + } } #[async_trait]