Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/asm/subprotocols/admin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@ thiserror.workspace = true
strata-asm-txs-admin = { workspace = true, features = ["test-utils"] }
strata-test-utils.workspace = true
rand.workspace = true
bitvec.workspace = true
bitcoin.workspace = true
43 changes: 21 additions & 22 deletions crates/asm/subprotocols/admin/src/authority.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,61 @@
use arbitrary::Arbitrary;
use borsh::{BorshDeserialize, BorshSerialize};
use strata_asm_txs_admin::actions::MultisigAction;
use strata_crypto::multisig::{
MultisigError, SchnorrMultisigConfig, SchnorrMultisigSignature, verify_multisig,
use strata_crypto::threshold_signature::{
SignatureSet, ThresholdConfig, ThresholdSignatureError, verify_threshold_signatures,
};
use strata_primitives::roles::Role;

/// Manages multisignature operations for a given role and key set, with replay protection via a
/// seqno.
#[derive(Clone, Debug, Eq, PartialEq, Arbitrary, BorshDeserialize, BorshSerialize)]
/// Manages threshold signature operations for a given role and key set, with replay protection via
/// a seqno.
#[derive(Clone, Debug, Eq, PartialEq, BorshDeserialize, BorshSerialize)]
pub struct MultisigAuthority {
/// The role of this multisignature authority.
/// The role of this threshold signature authority.
role: Role,
/// The public keys of all grant-holders authorized to sign.
config: SchnorrMultisigConfig,
/// Sequence number for the multisig configuration. It increases on each valid action.
config: ThresholdConfig,
/// Sequence number for the threshold configuration. It increases on each valid action.
/// This is used to prevent replay attacks.
seqno: u64,
}

impl MultisigAuthority {
pub fn new(role: Role, config: SchnorrMultisigConfig) -> Self {
pub fn new(role: Role, config: ThresholdConfig) -> Self {
Self {
role,
config,
seqno: 0,
}
}

/// The role authorized to perform multisig operations.
/// The role authorized to perform threshold signature operations.
pub fn role(&self) -> Role {
self.role
}

/// Borrow the current multisig configuration.
pub fn config(&self) -> &SchnorrMultisigConfig {
/// Borrow the current threshold configuration.
pub fn config(&self) -> &ThresholdConfig {
&self.config
}

/// Mutably borrow the multisig configuration.
pub fn config_mut(&mut self) -> &mut SchnorrMultisigConfig {
/// Mutably borrow the threshold configuration.
pub fn config_mut(&mut self) -> &mut ThresholdConfig {
&mut self.config
}

/// Verify that `signature` is a valid threshold signature for `action` under the current config
/// and seqno.
/// Verifies a set of ECDSA signatures against a threshold configuration.
///
/// Uses the generic multisig verification function to orchestrate the workflow.
/// This function is intentionally ECDSA-specific as part of the hardware wallet
/// compatibility design (BIP-137 format support). A trait-based abstraction
/// could be added in the future if multiple signature schemes are needed.
pub fn verify_action_signature(
&self,
action: &MultisigAction,
signature: &SchnorrMultisigSignature,
) -> Result<(), MultisigError> {
signatures: &SignatureSet,
) -> Result<(), ThresholdSignatureError> {
// Compute the msg to sign by combining UpdateAction with sequence no
let sig_hash = action.compute_sighash(self.seqno);

// Use the generic multisig verification function
verify_multisig(&self.config, signature, &sig_hash.into())
verify_threshold_signatures(&self.config, signatures.signatures(), &sig_hash.into())
}

/// Increments the seqno.
Expand Down
25 changes: 12 additions & 13 deletions crates/asm/subprotocols/admin/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use arbitrary::Arbitrary;
use borsh::{BorshDeserialize, BorshSerialize};
use strata_crypto::multisig::SchnorrMultisigConfig;
use strata_crypto::threshold_signature::ThresholdConfig;
use strata_primitives::roles::Role;

/// Parameters for the admnistration subprotocol, containing MultisigConfig for each role.
/// Parameters for the admnistration subprotocol, containing ThresholdConfig for each role.
///
/// Design choice: Uses individual named fields rather than `Vec<(Role, MultisigConfig)>`
/// Design choice: Uses individual named fields rather than `Vec<(Role, ThresholdConfig)>`
/// to ensure structural completeness - the compiler guarantees all 4 config fields are
/// provided when constructing this struct. However, it does NOT prevent logical errors
/// like using the same config for multiple roles or mismatched role-field assignments.
/// The benefit is avoiding missing fields at compile-time rather than runtime validation.
#[derive(Clone, Debug, Eq, PartialEq, Arbitrary, BorshDeserialize, BorshSerialize)]
#[derive(Clone, Debug, Eq, PartialEq, BorshDeserialize, BorshSerialize)]
pub struct AdministrationSubprotoParams {
/// MultisigConfig for [StrataAdministrator](Role::StrataAdministrator).
pub strata_administrator: SchnorrMultisigConfig,
/// ThresholdConfig for [StrataAdministrator](Role::StrataAdministrator).
pub strata_administrator: ThresholdConfig,

/// MultisigConfig for [StrataSequencerManager](Role::StrataSequencerManager).
pub strata_sequencer_manager: SchnorrMultisigConfig,
/// ThresholdConfig for [StrataSequencerManager](Role::StrataSequencerManager).
pub strata_sequencer_manager: ThresholdConfig,

/// The confirmation depth (CD) setting: after an update transaction receives this many
/// confirmations, the update is enacted automatically. During this confirmation period,
Expand All @@ -26,8 +25,8 @@ pub struct AdministrationSubprotoParams {

impl AdministrationSubprotoParams {
pub fn new(
strata_administrator: SchnorrMultisigConfig,
strata_sequencer_manager: SchnorrMultisigConfig,
strata_administrator: ThresholdConfig,
strata_sequencer_manager: ThresholdConfig,
confirmation_depth: u32,
) -> Self {
Self {
Expand All @@ -37,14 +36,14 @@ impl AdministrationSubprotoParams {
}
}

pub fn get_config(&self, role: Role) -> &SchnorrMultisigConfig {
pub fn get_config(&self, role: Role) -> &ThresholdConfig {
match role {
Role::StrataAdministrator => &self.strata_administrator,
Role::StrataSequencerManager => &self.strata_sequencer_manager,
}
}

pub fn get_all_authorities(self) -> Vec<(Role, SchnorrMultisigConfig)> {
pub fn get_all_authorities(self) -> Vec<(Role, ThresholdConfig)> {
vec![
(Role::StrataAdministrator, self.strata_administrator),
(Role::StrataSequencerManager, self.strata_sequencer_manager),
Expand Down
6 changes: 3 additions & 3 deletions crates/asm/subprotocols/admin/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use strata_asm_txs_admin::actions::UpdateId;
use strata_crypto::multisig::MultisigError;
use strata_crypto::threshold_signature::ThresholdSignatureError;
use thiserror::Error;

/// Top-level error type for the administration subprotocol, composed of smaller error categories.
Expand All @@ -13,7 +13,7 @@ pub enum AdministrationError {
#[error("no pending update found for action_id = {0:?}")]
UnknownAction(UpdateId),

/// Indicates a multisig error (configuration, aggregation, or signature validation).
/// Indicates a threshold signature error (configuration or signature validation).
#[error(transparent)]
Multisig(#[from] MultisigError),
ThresholdSignature(#[from] ThresholdSignatureError),
}
Loading
Loading