Skip to content

Commit aa909f4

Browse files
committed
chore: panic when store invariant is violated
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
1 parent b102f4c commit aa909f4

1 file changed

Lines changed: 15 additions & 11 deletions

File tree

crates/amaru/src/stages/consensus/forward_chain/chain_follower.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ impl<H: IsHeader + Clone + Send> ChainFollower<H> {
145145
})
146146
}
147147

148+
#[allow(clippy::panic)]
148149
pub fn next_op(&mut self, store: Arc<dyn ReadOnlyChainStore<H>>) -> Option<ClientOp<H>> {
149150
// is this initial rollback?
150151
if let Some(ref init_tip) = self.initial {
@@ -167,12 +168,10 @@ impl<H: IsHeader + Clone + Send> ChainFollower<H> {
167168
trace!(forwarded = %child.point(), anchor = ?self.anchor, "forwarding from store at origin");
168169
return Some(ClientOp::Forward(child));
169170
}
170-
None => {
171-
// FIXME: this seems possible in some circumstances given how our DB is structured
172-
// but this should never happen in practice. Perhaps turn into a proper `panic!`?
173-
warn!(intersection = ?self.intersection, child = %point, anchor = ?self.anchor, "child not found in store");
174-
return None;
175-
}
171+
None => panic!(
172+
"Store invariant violated:\nnext_best_chain returned {} but header not in store (intersection: {:?}, anchor: {:?})",
173+
point, self.intersection, self.anchor
174+
),
176175
}
177176
}
178177
None => {
@@ -182,7 +181,12 @@ impl<H: IsHeader + Clone + Send> ChainFollower<H> {
182181
}
183182
}
184183

185-
self.ops.pop_front()
184+
if let Some(op) = self.ops.pop_front() {
185+
self.intersection = op.tip();
186+
Some(op)
187+
} else {
188+
None
189+
}
186190
}
187191

188192
pub fn add_op(&mut self, op: ClientOp<H>) {
@@ -248,11 +252,11 @@ pub(crate) mod tests {
248252
fn find_headers_starting_at_tip() {
249253
let store = mk_in_memory_store(CHAIN_47);
250254

251-
let tip = store.get_point(TIP_47);
255+
let tip_point = store.get_point(TIP_47);
252256
let points = [store.get_point(TIP_47)];
253-
let start = Tip(tip.clone(), store.get_height(TIP_47));
257+
let start = Tip(tip_point.clone(), store.get_height(TIP_47));
254258

255-
let mut chain_follower = ChainFollower::new(store.clone(), &tip, &points).unwrap();
259+
let mut chain_follower = ChainFollower::new(store.clone(), &tip_point, &points).unwrap();
256260

257261
assert_eq!(
258262
chain_follower.next_op(store.clone()),
@@ -343,6 +347,7 @@ pub(crate) mod tests {
343347
}
344348

345349
#[test]
350+
#[should_panic(expected = "Store invariant violated")]
346351
fn next_op_returns_none_given_it_fails_to_load_child_header() {
347352
let store = mk_in_memory_store(CHAIN_47);
348353
let unstored_header = run(any_header_with_parent(Hash::from(
@@ -364,7 +369,6 @@ pub(crate) mod tests {
364369
let mut chain_follower = ChainFollower::new(store.clone(), &tip, &points).unwrap();
365370

366371
let _ = chain_follower.next_op(store.clone()); // initial rollback
367-
assert_eq!(chain_follower.next_op(store.clone()), None);
368372
}
369373

370374
// HELPERS

0 commit comments

Comments
 (0)