Skip to content

Commit

Permalink
Add configurable max-savepoints and savepoint-interval (#4191)
Browse files Browse the repository at this point in the history
Co-authored-by: raph <raphjaph@protonmail.com>
  • Loading branch information
emilcondrea and raphjaph authored Jan 27, 2025
1 parent 0a0916a commit bfcd096
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 10 deletions.
27 changes: 17 additions & 10 deletions src/index/reorg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ impl Display for Error {

impl std::error::Error for Error {}

const MAX_SAVEPOINTS: u32 = 2;
const SAVEPOINT_INTERVAL: u32 = 10;
const CHAIN_TIP_DISTANCE: u32 = 21;

pub(crate) struct Reorg {}

impl Reorg {
Expand All @@ -32,8 +28,10 @@ impl Reorg {
match index.block_hash(height.checked_sub(1))? {
Some(index_prev_blockhash) if index_prev_blockhash == bitcoind_prev_blockhash => Ok(()),
Some(index_prev_blockhash) if index_prev_blockhash != bitcoind_prev_blockhash => {
let savepoint_interval = u32::try_from(index.settings.savepoint_interval()).unwrap();
let max_savepoints = u32::try_from(index.settings.max_savepoints()).unwrap();
let max_recoverable_reorg_depth =
(MAX_SAVEPOINTS - 1) * SAVEPOINT_INTERVAL + height % SAVEPOINT_INTERVAL;
(max_savepoints - 1) * savepoint_interval + height % savepoint_interval;

for depth in 1..max_recoverable_reorg_depth {
let index_block_hash = index.block_hash(height.checked_sub(depth))?;
Expand Down Expand Up @@ -94,9 +92,13 @@ impl Reorg {
.unwrap_or(0);

let blocks = index.client.get_blockchain_info()?.headers;
let result = (height < SAVEPOINT_INTERVAL.into()
|| height.saturating_sub(last_savepoint_height) >= SAVEPOINT_INTERVAL.into())
&& blocks.saturating_sub(height) <= CHAIN_TIP_DISTANCE.into();

let savepoint_interval = u64::try_from(index.settings.savepoint_interval()).unwrap();
let max_savepoints = u64::try_from(index.settings.max_savepoints()).unwrap();

let result = (height < savepoint_interval
|| height.saturating_sub(last_savepoint_height) >= savepoint_interval)
&& blocks.saturating_sub(height) <= savepoint_interval * max_savepoints + 1;

log::trace!(
"is_savepoint_required={}: height={}, last_savepoint_height={}, blocks={}",
Expand All @@ -119,7 +121,11 @@ impl Reorg {

let savepoints = wtx.list_persistent_savepoints()?.collect::<Vec<u64>>();

if savepoints.len() >= usize::try_from(MAX_SAVEPOINTS).unwrap() {
if savepoints.len() >= index.settings.max_savepoints() {
log::info!(
"Cleaning up savepoints, keeping max {}",
index.settings.max_savepoints()
);
wtx.delete_persistent_savepoint(savepoints.into_iter().min().unwrap())?;
}

Expand All @@ -128,7 +134,8 @@ impl Reorg {

let wtx = index.begin_write()?;

log::info!("creating savepoint at height {}", height);
log::info!("Creating savepoint at height {}", height);

wtx.persistent_savepoint()?;

wtx
Expand Down
7 changes: 7 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ pub struct Options {
help = "Commit to index every <COMMIT_INTERVAL> blocks. [default: 5000]"
)]
pub(crate) commit_interval: Option<usize>,
#[arg(
long,
help = "Create a savepoint every <SAVEPOINT_INTERVAL> blocks. [default: 10]"
)]
pub(crate) savepoint_interval: Option<usize>,
#[arg(long, help = "Store maximum <MAX_SAVEPOINTS> blocks. [default: 2]")]
pub(crate) max_savepoints: Option<usize>,
#[arg(long, help = "Load configuration from <CONFIG>.")]
pub(crate) config: Option<PathBuf>,
#[arg(long, help = "Load configuration from <CONFIG_DIR>.")]
Expand Down
42 changes: 42 additions & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub struct Settings {
bitcoin_rpc_username: Option<String>,
chain: Option<Chain>,
commit_interval: Option<usize>,
savepoint_interval: Option<usize>,
max_savepoints: Option<usize>,
config: Option<PathBuf>,
config_dir: Option<PathBuf>,
cookie_file: Option<PathBuf>,
Expand Down Expand Up @@ -115,6 +117,8 @@ impl Settings {
bitcoin_rpc_username: self.bitcoin_rpc_username.or(source.bitcoin_rpc_username),
chain: self.chain.or(source.chain),
commit_interval: self.commit_interval.or(source.commit_interval),
savepoint_interval: self.savepoint_interval.or(source.savepoint_interval),
max_savepoints: self.max_savepoints.or(source.max_savepoints),
config: self.config.or(source.config),
config_dir: self.config_dir.or(source.config_dir),
cookie_file: self.cookie_file.or(source.cookie_file),
Expand Down Expand Up @@ -159,6 +163,8 @@ impl Settings {
.or(options.testnet4.then_some(Chain::Testnet4))
.or(options.chain_argument),
commit_interval: options.commit_interval,
savepoint_interval: options.savepoint_interval,
max_savepoints: options.max_savepoints,
config: options.config,
config_dir: options.config_dir,
cookie_file: options.cookie_file,
Expand Down Expand Up @@ -247,6 +253,8 @@ impl Settings {
bitcoin_rpc_username: get_string("BITCOIN_RPC_USERNAME"),
chain: get_chain("CHAIN")?,
commit_interval: get_usize("COMMIT_INTERVAL")?,
savepoint_interval: get_usize("SAVEPOINT_INTERVAL")?,
max_savepoints: get_usize("MAX_SAVEPOINTS")?,
config: get_path("CONFIG"),
config_dir: get_path("CONFIG_DIR"),
cookie_file: get_path("COOKIE_FILE"),
Expand Down Expand Up @@ -277,6 +285,8 @@ impl Settings {
bitcoin_rpc_limit: None,
chain: Some(Chain::Regtest),
commit_interval: None,
savepoint_interval: None,
max_savepoints: None,
config: None,
config_dir: None,
cookie_file: None,
Expand Down Expand Up @@ -344,6 +354,8 @@ impl Settings {
bitcoin_rpc_username: self.bitcoin_rpc_username,
chain: Some(chain),
commit_interval: Some(self.commit_interval.unwrap_or(5000)),
savepoint_interval: Some(self.savepoint_interval.unwrap_or(10)),
max_savepoints: Some(self.max_savepoints.unwrap_or(2)),
config: None,
config_dir: None,
cookie_file: Some(cookie_file),
Expand Down Expand Up @@ -470,6 +482,14 @@ impl Settings {
self.commit_interval.unwrap()
}

pub fn savepoint_interval(&self) -> usize {
self.savepoint_interval.unwrap()
}

pub fn max_savepoints(&self) -> usize {
self.max_savepoints.unwrap()
}

pub fn cookie_file(&self) -> Result<PathBuf> {
if let Some(cookie_file) = &self.cookie_file {
return Ok(cookie_file.clone());
Expand Down Expand Up @@ -933,6 +953,20 @@ mod tests {
assert_eq!(arguments.options.commit_interval, Some(500));
}

#[test]
fn setting_savepoint_interval() {
let arguments =
Arguments::try_parse_from(["ord", "--savepoint-interval", "500", "index", "update"]).unwrap();
assert_eq!(arguments.options.savepoint_interval, Some(500));
}

#[test]
fn setting_max_savepoints() {
let arguments =
Arguments::try_parse_from(["ord", "--max-savepoints", "10", "index", "update"]).unwrap();
assert_eq!(arguments.options.max_savepoints, Some(10));
}

#[test]
fn index_runes() {
assert!(parse(&["--chain=signet", "--index-runes"]).index_runes_raw());
Expand Down Expand Up @@ -1032,6 +1066,8 @@ mod tests {
("BITCOIN_RPC_USERNAME", "bitcoin username"),
("CHAIN", "signet"),
("COMMIT_INTERVAL", "1"),
("SAVEPOINT_INTERVAL", "10"),
("MAX_SAVEPOINTS", "2"),
("CONFIG", "config"),
("CONFIG_DIR", "config dir"),
("COOKIE_FILE", "cookie file"),
Expand Down Expand Up @@ -1065,6 +1101,8 @@ mod tests {
bitcoin_rpc_username: Some("bitcoin username".into()),
chain: Some(Chain::Signet),
commit_interval: Some(1),
savepoint_interval: Some(10),
max_savepoints: Some(2),
config: Some("config".into()),
config_dir: Some("config dir".into()),
cookie_file: Some("cookie file".into()),
Expand Down Expand Up @@ -1111,6 +1149,8 @@ mod tests {
"--bitcoin-rpc-username=bitcoin username",
"--chain=signet",
"--commit-interval=1",
"--savepoint-interval=10",
"--max-savepoints=2",
"--config=config",
"--config-dir=config dir",
"--cookie-file=cookie file",
Expand All @@ -1137,6 +1177,8 @@ mod tests {
bitcoin_rpc_username: Some("bitcoin username".into()),
chain: Some(Chain::Signet),
commit_interval: Some(1),
savepoint_interval: Some(10),
max_savepoints: Some(2),
config: Some("config".into()),
config_dir: Some("config dir".into()),
cookie_file: Some("cookie file".into()),
Expand Down
2 changes: 2 additions & 0 deletions tests/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ fn default() {
"bitcoin_rpc_username": null,
"chain": "mainnet",
"commit_interval": 5000,
"savepoint_interval": 10,
"max_savepoints": 2,
"config": null,
"config_dir": null,
"cookie_file": ".*\.cookie",
Expand Down

0 comments on commit bfcd096

Please sign in to comment.