Skip to content

Commit

Permalink
Denominate signer checkpoint interval in Bitcoin blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
keppel committed Feb 13, 2024
1 parent cd6a7fc commit aa05e22
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 21 deletions.
10 changes: 5 additions & 5 deletions src/bin/nomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1225,13 +1225,13 @@ pub struct SignerCmd {
#[clap(long, default_value_t = 0.1)]
max_sigset_change_rate: f64,

/// The minimum age of a checkpoint before the signer will contribute its
/// signature. This setting can be used to change the rate at which the
/// The minimum number of Bitcoin blocks that must be mined before the signer will contribute its
/// signature to the current signing checkpoint. This setting can be used to change the rate at which the
/// network produces checkpoints (higher values cause less frequent checkpoints).
///
/// Signatures will always be contributed to previously completed checkpoints.
#[clap(long, default_value_t = 120)]
min_checkpoint_minutes: u64,
#[clap(long, default_value_t = 12)]
min_blocks_per_checkpoint: u64,

#[clap(long)]
prometheus_addr: Option<std::net::SocketAddr>,
Expand All @@ -1255,7 +1255,7 @@ impl SignerCmd {
self.xpriv_paths.clone(),
self.max_withdrawal_rate,
self.max_sigset_change_rate,
self.min_checkpoint_minutes * 60,
self.min_blocks_per_checkpoint,
self.reset_limits_at_index,
// TODO: check for custom RPC port, allow config, etc
|| nomic::app_client("http://localhost:26657").with_wallet(wallet()),
Expand Down
43 changes: 27 additions & 16 deletions src/bitcoin/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub struct Signer<W, F> {
xprivs: Vec<ExtendedPrivKey>,
max_withdrawal_rate: f64,
max_sigset_change_rate: f64,
min_checkpoint_seconds: u64,
min_blocks_per_checkpoint: u64,
reset_index: Option<u32>,
app_client: F,
exporter_addr: Option<SocketAddr>,
Expand Down Expand Up @@ -158,8 +158,8 @@ where
/// - `max_sigset_change_rate`: The maximum rate at which the signatory set
/// can change in a 24-hour period, temporarily halting signing if the limit
/// is reached.
/// - `min_checkpoint_seconds`: The minimum amount of time that must pass
/// before this signer will contribute its signature.
/// - `min_blocks_per_checkpoint`: The minimum number of new Bitcoin blocks
/// that must be mined before this signer will contribute its signature.
/// - `reset_index`: A checkpoint index at which the rate limits should be
/// reset, used to manually override the limits if the signer has checked on
/// the pending withdrawals and decided they are legitimate.
Expand All @@ -170,7 +170,7 @@ where
xprivs: Vec<ExtendedPrivKey>,
max_withdrawal_rate: f64,
max_sigset_change_rate: f64,
min_checkpoint_seconds: u64,
min_blocks_per_checkpoint: u64,
reset_index: Option<u32>,
app_client: F,
exporter_addr: Option<SocketAddr>,
Expand All @@ -183,7 +183,7 @@ where
xprivs,
max_withdrawal_rate,
max_sigset_change_rate,
min_checkpoint_seconds,
min_blocks_per_checkpoint,
reset_index,
app_client,
exporter_addr,
Expand Down Expand Up @@ -332,7 +332,7 @@ where

let (status, timestamp) = self
.client()
.query(|app| {
.query(|app: InnerApp| {
let cp = app.bitcoin.checkpoints.get(index)?;
Ok((cp.status, cp.create_time()))
})
Expand All @@ -356,16 +356,27 @@ where

if matches!(status, CheckpointStatus::Signing) {
self.check_change_rates().await?;
let now_seconds = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
if timestamp + self.min_checkpoint_seconds > now_seconds {
info!(
"Checkpoint is too recent, waiting {} seconds",
(timestamp + self.min_checkpoint_seconds) - now_seconds
);
return Ok(false);
let current_btc_height = self
.client()
.query(|app: InnerApp| Ok(app.bitcoin.headers.height()?))
.await? as u64;
let last_signed_btc_height: Option<u64> = self
.client()
.query(|app: InnerApp| Ok(app.bitcoin.checkpoints.get(index)?.signed_at_btc_height))
.await?
.map(|v| v as u64);

if let Some(last_signed_btc_height) = last_signed_btc_height {
if current_btc_height < last_signed_btc_height + self.min_blocks_per_checkpoint {
let delta = last_signed_btc_height + self.min_blocks_per_checkpoint
- current_btc_height;
info!(
"Checkpoint is too recent, {} more Bitcoin block{} required",
delta,
if delta == 1 { "" } else { "s" },
);
return Ok(false);
}
}
}

Expand Down

0 comments on commit aa05e22

Please sign in to comment.