Skip to content

Merge release/signer-3.1.0.0.8.1 to master #6043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions libsigner/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ struct BlockEvent {
#[serde(with = "prefix_hex")]
index_block_hash: StacksBlockId,
#[serde(with = "prefix_opt_hex")]
#[serde(default)]
signer_signature_hash: Option<Sha512Trunc256Sum>,
#[serde(with = "prefix_hex")]
consensus_hash: ConsensusHash,
Expand Down
6 changes: 6 additions & 0 deletions stacks-signer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to the versioning scheme outlined in the [README.md](README.md).

## [3.1.0.0.8.1]

### Added

- The signer will now check if their associated stacks-node has processed the parent block for a block proposal before submitting that block proposal. If it cannot confirm that the parent block has been processed, it waits a default time of 15s before submitting, configurable via `proposal_wait_for_parent_time_secs` in the signer config.toml.

## [3.1.0.0.8.0]

### Changed
Expand Down
3 changes: 3 additions & 0 deletions stacks-signer/src/chainstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ pub struct ProposalEvalConfig {
/// Time following the last block of the previous tenure's global acceptance that a signer will consider an attempt by
/// the new miner to reorg it as valid towards miner activity
pub reorg_attempts_activity_timeout: Duration,
/// Time to wait before submitting a block proposal to the stacks-node
pub proposal_wait_for_parent_time: Duration,
}

impl From<&SignerConfig> for ProposalEvalConfig {
Expand All @@ -152,6 +154,7 @@ impl From<&SignerConfig> for ProposalEvalConfig {
tenure_idle_timeout: value.tenure_idle_timeout,
reorg_attempts_activity_timeout: value.reorg_attempts_activity_timeout,
tenure_idle_timeout_buffer: value.tenure_idle_timeout_buffer,
proposal_wait_for_parent_time: value.proposal_wait_for_parent_time,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions stacks-signer/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ pub(crate) mod tests {
tenure_idle_timeout_buffer: config.tenure_idle_timeout_buffer,
block_proposal_max_age_secs: config.block_proposal_max_age_secs,
reorg_attempts_activity_timeout: config.reorg_attempts_activity_timeout,
proposal_wait_for_parent_time: config.proposal_wait_for_parent_time,
}
}

Expand Down
19 changes: 19 additions & 0 deletions stacks-signer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const DEFAULT_REORG_ATTEMPTS_ACTIVITY_TIMEOUT_MS: u64 = 200_000;
/// Default number of seconds to add to the tenure extend time, after computing the idle timeout,
/// to allow for clock skew between the signer and the miner
const DEFAULT_TENURE_IDLE_TIMEOUT_BUFFER_SECS: u64 = 2;
/// Default time (in ms) to wait before submitting a proposal if we
/// cannot determine that our stacks-node has processed the parent
/// block
const DEFAULT_PROPOSAL_WAIT_TIME_FOR_PARENT_SECS: u64 = 15;

#[derive(thiserror::Error, Debug)]
/// An error occurred parsing the provided configuration
Expand Down Expand Up @@ -175,6 +179,9 @@ pub struct SignerConfig {
pub reorg_attempts_activity_timeout: Duration,
/// The running mode for the signer (dry-run or normal)
pub signer_mode: SignerConfigMode,
/// Time to wait before submitting a block proposal to the stacks-node if we cannot
/// determine that the stacks-node has processed the parent
pub proposal_wait_for_parent_time: Duration,
}

/// The parsed configuration for the signer
Expand Down Expand Up @@ -221,6 +228,9 @@ pub struct GlobalConfig {
/// Time following the last block of the previous tenure's global acceptance that a signer will consider an attempt by
/// the new miner to reorg it as valid towards miner activity
pub reorg_attempts_activity_timeout: Duration,
/// Time to wait before submitting a block proposal to the stacks-node if we cannot
/// determine that the stacks-node has processed the parent
pub proposal_wait_for_parent_time: Duration,
/// Is this signer binary going to be running in dry-run mode?
pub dry_run: bool,
}
Expand Down Expand Up @@ -268,6 +278,8 @@ struct RawConfigFile {
/// Time (in millisecs) following a block's global acceptance that a signer will consider an attempt by a miner
/// to reorg the block as valid towards miner activity
pub reorg_attempts_activity_timeout_ms: Option<u64>,
/// Time to wait (in millisecs) before submitting a block proposal to the stacks-node
pub proposal_wait_for_parent_time_secs: Option<u64>,
/// Is this signer binary going to be running in dry-run mode?
pub dry_run: Option<bool>,
}
Expand Down Expand Up @@ -385,6 +397,12 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
.unwrap_or(DEFAULT_TENURE_IDLE_TIMEOUT_BUFFER_SECS),
);

let proposal_wait_for_parent_time = Duration::from_secs(
raw_data
.proposal_wait_for_parent_time_secs
.unwrap_or(DEFAULT_PROPOSAL_WAIT_TIME_FOR_PARENT_SECS),
);

Ok(Self {
node_host: raw_data.node_host,
endpoint,
Expand All @@ -405,6 +423,7 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
reorg_attempts_activity_timeout,
dry_run,
tenure_idle_timeout_buffer,
proposal_wait_for_parent_time,
})
}
}
Expand Down
2 changes: 2 additions & 0 deletions stacks-signer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ pub trait Signer<T: SignerEventTrait>: Debug + Display {
fn has_unprocessed_blocks(&self) -> bool;
/// Get a reference to the local state machine of the signer
fn get_local_state_machine(&self) -> &LocalStateMachine;
/// Get the number of pending block proposals
fn get_pending_proposals_count(&self) -> u64;
}

/// A wrapper around the running signer type for the signer
Expand Down
14 changes: 14 additions & 0 deletions stacks-signer/src/runloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ pub struct StateInfo {
/// The local state machines for the running signers
/// as a pair of (reward-cycle, state-machine)
pub signer_state_machines: Vec<(u64, Option<LocalStateMachine>)>,
/// The number of pending block proposals for this signer
pub pending_proposals_count: u64,
}

/// The signer result that can be sent across threads
Expand Down Expand Up @@ -320,6 +322,7 @@ impl<Signer: SignerTrait<T>, T: StacksMessageCodec + Clone + Send + Debug> RunLo
tenure_idle_timeout_buffer: self.config.tenure_idle_timeout_buffer,
block_proposal_max_age_secs: self.config.block_proposal_max_age_secs,
reorg_attempts_activity_timeout: self.config.reorg_attempts_activity_timeout,
proposal_wait_for_parent_time: self.config.proposal_wait_for_parent_time,
}))
}

Expand Down Expand Up @@ -523,6 +526,17 @@ impl<Signer: SignerTrait<T>, T: StacksMessageCodec + Clone + Send + Debug>
)
})
.collect(),
pending_proposals_count: self
.stacks_signers
.values()
.find_map(|signer| {
if let ConfiguredSigner::RegisteredSigner(signer) = signer {
Some(signer.get_pending_proposals_count())
} else {
None
}
})
.unwrap_or(0),
};
info!("Signer status check requested: {state_info:?}");

Expand Down
35 changes: 25 additions & 10 deletions stacks-signer/src/signerdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,12 +1180,18 @@ impl SignerDb {
/// If found, remove it from the pending table.
pub fn get_and_remove_pending_block_validation(
&self,
) -> Result<Option<Sha512Trunc256Sum>, DBError> {
let qry = "DELETE FROM block_validations_pending WHERE signer_signature_hash = (SELECT signer_signature_hash FROM block_validations_pending ORDER BY added_time ASC LIMIT 1) RETURNING signer_signature_hash";
) -> Result<Option<(Sha512Trunc256Sum, u64)>, DBError> {
let qry = "DELETE FROM block_validations_pending WHERE signer_signature_hash = (SELECT signer_signature_hash FROM block_validations_pending ORDER BY added_time ASC LIMIT 1) RETURNING signer_signature_hash, added_time";
let args = params![];
let mut stmt = self.db.prepare(qry)?;
let sighash: Option<String> = stmt.query_row(args, |row| row.get(0)).optional()?;
Ok(sighash.and_then(|sighash| Sha512Trunc256Sum::from_hex(&sighash).ok()))
let result: Option<(String, i64)> = stmt
.query_row(args, |row| Ok((row.get(0)?, row.get(1)?)))
.optional()?;
Ok(result.and_then(|(sighash, ts_i64)| {
let signer_sighash = Sha512Trunc256Sum::from_hex(&sighash).ok()?;
let ts = u64::try_from(ts_i64).ok()?;
Some((signer_sighash, ts))
}))
}

/// Remove a pending block validation
Expand Down Expand Up @@ -2093,20 +2099,29 @@ mod tests {
db.insert_pending_block_validation(&Sha512Trunc256Sum([0x03; 32]), 3000)
.unwrap();

let pending_hash = db.get_and_remove_pending_block_validation().unwrap();
assert_eq!(pending_hash, Some(Sha512Trunc256Sum([0x01; 32])));
let (pending_hash, _) = db
.get_and_remove_pending_block_validation()
.unwrap()
.unwrap();
assert_eq!(pending_hash, Sha512Trunc256Sum([0x01; 32]));

let pendings = db.get_all_pending_block_validations().unwrap();
assert_eq!(pendings.len(), 2);

let pending_hash = db.get_and_remove_pending_block_validation().unwrap();
assert_eq!(pending_hash, Some(Sha512Trunc256Sum([0x02; 32])));
let (pending_hash, _) = db
.get_and_remove_pending_block_validation()
.unwrap()
.unwrap();
assert_eq!(pending_hash, Sha512Trunc256Sum([0x02; 32]));

let pendings = db.get_all_pending_block_validations().unwrap();
assert_eq!(pendings.len(), 1);

let pending_hash = db.get_and_remove_pending_block_validation().unwrap();
assert_eq!(pending_hash, Some(Sha512Trunc256Sum([0x03; 32])));
let (pending_hash, _) = db
.get_and_remove_pending_block_validation()
.unwrap()
.unwrap();
assert_eq!(pending_hash, Sha512Trunc256Sum([0x03; 32]));

let pendings = db.get_all_pending_block_validations().unwrap();
assert!(pendings.is_empty());
Expand Down
1 change: 1 addition & 0 deletions stacks-signer/src/tests/chainstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ fn setup_test_environment(
tenure_idle_timeout: Duration::from_secs(300),
tenure_idle_timeout_buffer: Duration::from_secs(2),
reorg_attempts_activity_timeout: Duration::from_secs(3),
proposal_wait_for_parent_time: Duration::from_secs(0),
},
};

Expand Down
Loading
Loading