Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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