Skip to content

Commit 12fbf11

Browse files
committed
fix: deep re-org
1 parent bd2b25a commit 12fbf11

File tree

1 file changed

+48
-23
lines changed

1 file changed

+48
-23
lines changed

components/chainhook-sdk/src/indexer/stacks/blocks_pool.rs

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use crate::{
2-
indexer::{
3-
database::BlocksDatabaseAccess, fork_scratch_pad::CONFIRMED_SEGMENT_MINIMUM_LENGTH,
4-
ChainSegment, ChainSegmentIncompatibility,
5-
},
2+
indexer::{database::BlocksDatabaseAccess, ChainSegment, ChainSegmentIncompatibility},
63
try_error, try_info,
74
utils::Context,
85
};
@@ -16,6 +13,8 @@ use hiro_system_kit::slog;
1613
use std::collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet};
1714
use std::sync::Arc;
1815

16+
const STACKS_CONFIRMED_SEGMENT_MINIMUM_LENGTH: i32 = 20;
17+
1918
pub struct StacksBlockPool {
2019
canonical_fork_id: usize,
2120
highest_competing_fork_height_delta: Option<u16>,
@@ -102,6 +101,18 @@ impl StacksBlockPool {
102101
}
103102
}
104103

104+
fn add_fork(&mut self, fork: ChainSegment) -> usize {
105+
let number_of_forks = self.forks.len();
106+
let mut next_fork_id = 0;
107+
for (index, (fork_id, _)) in self.forks.iter().enumerate() {
108+
if (index + 1) == number_of_forks {
109+
next_fork_id = fork_id + 1;
110+
}
111+
}
112+
self.forks.insert(next_fork_id, fork);
113+
next_fork_id
114+
}
115+
105116
pub fn process_block(
106117
&mut self,
107118
block: StacksBlockData,
@@ -135,14 +146,7 @@ impl StacksBlockPool {
135146
let (block_appended, mut new_fork) = fork.try_append_block(&block, ctx);
136147
if block_appended {
137148
if let Some(new_fork) = new_fork.take() {
138-
let number_of_forks = self.forks.len();
139-
let mut next_fork_id = 0;
140-
for (index, (fork_id, _)) in self.forks.iter().enumerate() {
141-
if (index + 1) == number_of_forks {
142-
next_fork_id = fork_id + 1;
143-
}
144-
}
145-
self.forks.insert(next_fork_id, new_fork);
149+
let next_fork_id = self.add_fork(new_fork);
146150
fork_updated = self.forks.get_mut(&next_fork_id);
147151
} else {
148152
fork_updated = Some(fork);
@@ -161,28 +165,49 @@ impl StacksBlockPool {
161165
);
162166
self.block_store
163167
.insert(block.block_identifier.clone(), block.clone());
164-
fork
165168
}
166169
None => {
167170
// Look for the orphan block in the blocks DB. If it already exists, it means we've received an old block and we
168171
// should just ignore it. This can happen if the Stacks node feeding us blocks is still catching up to our chain
169172
// tip.
170-
if let Some(db_access) = &self.database_access {
173+
let handled = if let Some(db_access) = &self.database_access {
171174
if let Ok(true) = db_access.block_exists(&block.block_identifier, ctx) {
172175
try_info!(
173176
ctx,
174177
"Ignoring previously processed block: Stacks {}",
175178
block.block_identifier
176179
);
177-
return Ok(None);
180+
true
181+
} else {
182+
// Check the new block's parent, perhaps this is a deep re-orged block segment we need to add to our
183+
// forks.
184+
if let Ok(true) =
185+
db_access.block_exists(&block.parent_block_identifier, ctx)
186+
{
187+
try_info!(
188+
ctx,
189+
"Appending new deep re-orged fork for block: Stacks {}",
190+
block.parent_block_identifier
191+
);
192+
let mut fork = ChainSegment::new();
193+
fork.append_block_identifier(&block.parent_block_identifier);
194+
self.add_fork(fork);
195+
true
196+
} else {
197+
false
198+
}
178199
}
200+
} else {
201+
false
202+
};
203+
if !handled {
204+
try_error!(
205+
ctx,
206+
"Unable to process orphan block: Stacks {}",
207+
block.block_identifier
208+
);
209+
return Err("Unable to process orphan Stacks block".to_string());
179210
}
180-
try_error!(
181-
ctx,
182-
"Unable to process orphan block: Stacks {}",
183-
block.block_identifier
184-
);
185-
return Err("Unable to process orphan Stacks block".to_string());
186211
}
187212
};
188213

@@ -321,12 +346,12 @@ impl StacksBlockPool {
321346
segment
322347
};
323348

324-
if canonical_segment.len() < CONFIRMED_SEGMENT_MINIMUM_LENGTH as usize {
349+
if canonical_segment.len() < STACKS_CONFIRMED_SEGMENT_MINIMUM_LENGTH as usize {
325350
ctx.try_log(|logger| slog::info!(logger, "No block to confirm"));
326351
return;
327352
}
328353
// Any block beyond 6th ancestor is considered as confirmed and can be pruned
329-
let cut_off = &canonical_segment[(CONFIRMED_SEGMENT_MINIMUM_LENGTH - 2) as usize];
354+
let cut_off = &canonical_segment[(STACKS_CONFIRMED_SEGMENT_MINIMUM_LENGTH - 2) as usize];
330355

331356
// Prune forks using the confirmed block
332357
let mut blocks_to_prune = vec![];

0 commit comments

Comments
 (0)