From f0b3c08eb75376554e3d6d27c530c4586ffbf1c4 Mon Sep 17 00:00:00 2001 From: Dave Grantham Date: Wed, 7 Oct 2026 20:11:41 -0600 Subject: [PATCH 1/2] migrate to multi-sig builder Signed-off-by: Dave Grantham --- Cargo.toml | 2 +- src/views/bls12381.rs | 16 ++++++++-------- src/views/bls12381_g1_fndsa512.rs | 4 ++-- src/views/bls12381_g1_mayo1.rs | 4 ++-- src/views/bls12381_g1_mayo2.rs | 4 ++-- src/views/bls12381_g1_mldsa65.rs | 4 ++-- src/views/ed25519.rs | 4 ++-- src/views/ed25519_fndsa512.rs | 4 ++-- src/views/ed25519_mayo2.rs | 4 ++-- src/views/ed25519_mldsa65.rs | 4 ++-- src/views/fn_dsa.rs | 4 ++-- src/views/lamport.rs | 23 +++++++++++++++-------- src/views/lamport_merkle.rs | 19 +++++++++++++++---- src/views/mayo.rs | 4 ++-- src/views/ml_dsa.rs | 4 ++-- src/views/nist_p.rs | 4 ++-- src/views/rsa.rs | 4 ++-- src/views/secp256k1.rs | 4 ++-- src/views/slh_dsa.rs | 4 ++-- src/views/xeddsa.rs | 9 +++++---- src/views/xmss.rs | 4 ++-- tests/merkle_lamport_tests.rs | 16 +++++++++++++--- 22 files changed, 89 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ce84996..bfb748c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ ml-kem = "0.3" multi-base = { version = "1.0", default-features = false } multi-codec = "1.5" multi-hash = "1.1" -multi-sig = "1.4" +multi-sig = "1.5" multi-trait = { version = "1.0", default-features = false } multi-util = "1.1" p256 = { version = "0.14", features = ["ecdsa", "ecdh"] } diff --git a/src/views/bls12381.rs b/src/views/bls12381.rs index 0d5fb41..e32c235 100644 --- a/src/views/bls12381.rs +++ b/src/views/bls12381.rs @@ -22,7 +22,7 @@ use blsful::{ use elliptic_curve::group::GroupEncoding; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms, views::bls12381::SchemeTypeId}; +use multi_sig::{Multisig, ViewBuilder, ms, views::bls12381::SchemeTypeId}; use multi_trait::TryDecodeFrom; use multi_util::{Varbytes, Varuint}; use rand_core::Rng; @@ -1202,7 +1202,7 @@ impl<'a> VerifyView for View<'a> { }; // get the signature scheme - let av = multisig.attr_view()?; + let av = ViewBuilder::new(multisig).attr().build()?; let sig_scheme = SchemeTypeId::try_from(av.scheme()?)?; match pubmk.codec { @@ -1212,7 +1212,7 @@ impl<'a> VerifyView for View<'a> { .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let group_encoding: G1Projective = { @@ -1273,11 +1273,11 @@ impl<'a> VerifyView for View<'a> { ); // get the share identifier - let av = multisig.threshold_attr_view()?; + let av = ViewBuilder::new(multisig).threshold_attr().build()?; let identifier = bytes_to_identifier(av.identifier()?)?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let value = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let bytes: [u8; 48] = value.as_slice().try_into().map_err(|_| { VerifyError::BadSignature("Invalid signature share bytes".to_string()) @@ -1316,7 +1316,7 @@ impl<'a> VerifyView for View<'a> { .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let group_encoding: G2Projective = { @@ -1374,11 +1374,11 @@ impl<'a> VerifyView for View<'a> { ); // get the share identifier - let av = multisig.threshold_attr_view()?; + let av = ViewBuilder::new(multisig).threshold_attr().build()?; let identifier = bytes_to_identifier(av.identifier()?)?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let value = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let bytes: [u8; 96] = value.as_slice().try_into().map_err(|_| { VerifyError::BadSignature("Invalid signature share bytes".to_string()) diff --git a/src/views/bls12381_g1_fndsa512.rs b/src/views/bls12381_g1_fndsa512.rs index 30a3ce1..dc5b2d4 100644 --- a/src/views/bls12381_g1_fndsa512.rs +++ b/src/views/bls12381_g1_fndsa512.rs @@ -19,7 +19,7 @@ use fn_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use zeroize::Zeroizing; const LOGN: u32 = FN_DSA_LOGN_512; @@ -211,7 +211,7 @@ impl<'a> VerifyView for View<'a> { .into()); } - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != bls::BLS_G1_SIG_LEN + signature_size(LOGN) { return Err(VerifyError::BadSignature("invalid hybrid signature length".into()).into()); diff --git a/src/views/bls12381_g1_mayo1.rs b/src/views/bls12381_g1_mayo1.rs index b1ec040..e96e3d1 100644 --- a/src/views/bls12381_g1_mayo1.rs +++ b/src/views/bls12381_g1_mayo1.rs @@ -16,7 +16,7 @@ use crate::{ use ml_dsa::signature::{Signer, Verifier}; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use pq_mayo::{KeyPair, Mayo1, Signature, VerifyingKey}; use zeroize::Zeroizing; @@ -199,7 +199,7 @@ impl<'a> VerifyView for View<'a> { .into()); } - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != HYBRID_SIG_LEN { return Err(VerifyError::BadSignature("invalid hybrid signature length".into()).into()); diff --git a/src/views/bls12381_g1_mayo2.rs b/src/views/bls12381_g1_mayo2.rs index e1e9d11..027da65 100644 --- a/src/views/bls12381_g1_mayo2.rs +++ b/src/views/bls12381_g1_mayo2.rs @@ -16,7 +16,7 @@ use crate::{ use ml_dsa::signature::{Signer, Verifier}; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use pq_mayo::{KeyPair, Mayo2, Signature, VerifyingKey}; use zeroize::Zeroizing; @@ -199,7 +199,7 @@ impl<'a> VerifyView for View<'a> { .into()); } - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != HYBRID_SIG_LEN { return Err(VerifyError::BadSignature("invalid hybrid signature length".into()).into()); diff --git a/src/views/bls12381_g1_mldsa65.rs b/src/views/bls12381_g1_mldsa65.rs index 3f11311..066c48f 100644 --- a/src/views/bls12381_g1_mldsa65.rs +++ b/src/views/bls12381_g1_mldsa65.rs @@ -19,7 +19,7 @@ use ml_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use zeroize::Zeroizing; const MLDSA65_SEED_LEN: usize = 32; @@ -211,7 +211,7 @@ impl<'a> VerifyView for View<'a> { .into()); } - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != HYBRID_SIG_LEN { return Err(VerifyError::BadSignature("invalid hybrid signature length".into()).into()); diff --git a/src/views/ed25519.rs b/src/views/ed25519.rs index b30010a..c5625ac 100644 --- a/src/views/ed25519.rs +++ b/src/views/ed25519.rs @@ -12,7 +12,7 @@ use ed25519_dalek::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use multi_trait::TryDecodeFrom; use multi_util::Varuint; use zeroize::Zeroizing; @@ -318,7 +318,7 @@ impl<'a> VerifyView for View<'a> { .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; // create the signature diff --git a/src/views/ed25519_fndsa512.rs b/src/views/ed25519_fndsa512.rs index a1a0f13..b91389a 100644 --- a/src/views/ed25519_fndsa512.rs +++ b/src/views/ed25519_fndsa512.rs @@ -18,7 +18,7 @@ use fn_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use zeroize::Zeroizing; const LOGN: u32 = FN_DSA_LOGN_512; @@ -223,7 +223,7 @@ impl<'a> VerifyView for View<'a> { } // Get signature bytes - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != ED25519_SIG_LEN + signature_size(LOGN) { diff --git a/src/views/ed25519_mayo2.rs b/src/views/ed25519_mayo2.rs index 34e4980..bc19210 100644 --- a/src/views/ed25519_mayo2.rs +++ b/src/views/ed25519_mayo2.rs @@ -12,7 +12,7 @@ use crate::{ use ed25519_dalek::{Signature as Ed25519Sig, SigningKey, VerifyingKey}; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use pq_mayo::{KeyPair, Mayo2}; use zeroize::Zeroizing; @@ -222,7 +222,7 @@ impl<'a> VerifyView for View<'a> { } // Get signature bytes - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != HYBRID_SIG_LEN { diff --git a/src/views/ed25519_mldsa65.rs b/src/views/ed25519_mldsa65.rs index d1b0503..c37ec54 100644 --- a/src/views/ed25519_mldsa65.rs +++ b/src/views/ed25519_mldsa65.rs @@ -18,7 +18,7 @@ use ml_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use zeroize::Zeroizing; const ED25519_SEED_LEN: usize = 32; @@ -226,7 +226,7 @@ impl<'a> VerifyView for View<'a> { } // Get signature bytes - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig_bytes.len() != HYBRID_SIG_LEN { diff --git a/src/views/fn_dsa.rs b/src/views/fn_dsa.rs index 3c4f977..fa2f099 100644 --- a/src/views/fn_dsa.rs +++ b/src/views/fn_dsa.rs @@ -15,7 +15,7 @@ use fn_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Views as _, ms}; +use multi_sig::{ViewBuilder, ms}; use ssh_encoding::{Decode, Encode}; use zeroize::Zeroizing; @@ -273,7 +273,7 @@ impl<'a> VerifyView for View<'a> { ConversionsError::PublicKeyFailure("invalid public key length".into()), )?; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig_bytes = sv.sig_bytes()?; let expected_sig_len = if key_bytes.len() == vrfy_key_size(FN_DSA_LOGN_512) { diff --git a/src/views/lamport.rs b/src/views/lamport.rs index 984d01f..0b5541e 100644 --- a/src/views/lamport.rs +++ b/src/views/lamport.rs @@ -20,7 +20,7 @@ use lamport_signature_plus::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Views as _, ms}; +use multi_sig::{ViewBuilder, ms}; use sha2::{Sha256, Sha384, Sha512}; use sha3::{Sha3_256, Sha3_384, Sha3_512}; use shake::{Shake128, Shake256}; @@ -603,7 +603,7 @@ impl<'a> VerifyView for View<'a> { let kd = dispatch_data_view(&pubmk)?; kd.key_bytes()? }; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; verify_bytes(pubmk.codec, key_bytes.as_slice(), &sig, msg_bytes) } @@ -745,7 +745,7 @@ mod tests { #[test] fn test_lamport_threshold_sign_combine() { - use multi_sig::Views as _; + use multi_sig::ViewBuilder as SigViewBuilder; use multi_util::CodecInfo as _; let mut rng = rand::rng(); @@ -796,17 +796,24 @@ mod tests { let acc = ms::Builder::new(Codec::LamportSha3256Sig) .try_build() .unwrap(); - let acc = acc - .threshold_view() + let acc = SigViewBuilder::new(&acc) + .threshold() + .build() .unwrap() .add_share(&share_sig_a) .unwrap(); - let acc = acc - .threshold_view() + let acc = SigViewBuilder::new(&acc) + .threshold() + .build() .unwrap() .add_share(&share_sig_c) .unwrap(); - let combined = acc.threshold_view().unwrap().combine().unwrap(); + let combined = SigViewBuilder::new(&acc) + .threshold() + .build() + .unwrap() + .combine() + .unwrap(); assert_eq!(combined.codec(), Codec::LamportSha3256Sig); // the combined signature verifies under the ORIGINAL public key diff --git a/src/views/lamport_merkle.rs b/src/views/lamport_merkle.rs index c10a216..d2515b0 100644 --- a/src/views/lamport_merkle.rs +++ b/src/views/lamport_merkle.rs @@ -31,7 +31,7 @@ use lamport_signature_plus::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{AttrId as MsAttrId, Views as _, ms}; +use multi_sig::{AttrId as MsAttrId, ViewBuilder, ms}; use zeroize::Zeroizing; /// Mt state wire format version byte (lamport_signature_plus 0.5.0). @@ -731,7 +731,7 @@ impl<'a> VerifyView for View<'a> { // wire depth (byte 0) and the signature wire depth (byte 0). let key_depth = wire_depth_at(key_bytes.as_slice(), 0)?; check_depth_attribute(&pubmk, key_depth)?; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let sig_depth = wire_depth_at(&sig, 0)?; if sig_depth != key_depth { @@ -1017,6 +1017,7 @@ mod tests { use crate::LAMPORT_MERKLE_KEY_CODECS; use crate::ViewBuilder; use multi_sig::AttrId as MsAttrId; + use multi_sig::ViewBuilder as SigViewBuilder; fn build_priv(codec: Codec, depth: u8) -> Multikey { Builder::new_from_random_bytes_with_depth(codec, depth, &mut rand::rng()) @@ -1312,10 +1313,20 @@ mod tests { .try_build() .unwrap(); for share_ms in [&s1, &s2] { - let next = acc.threshold_view().unwrap().add_share(share_ms).unwrap(); + let next = SigViewBuilder::new(&acc) + .threshold() + .build() + .unwrap() + .add_share(share_ms) + .unwrap(); acc = next; } - let combined = acc.threshold_view().unwrap().combine().unwrap(); + let combined = SigViewBuilder::new(&acc) + .threshold() + .build() + .unwrap() + .combine() + .unwrap(); ViewBuilder::new(&pk) .verify() .build() diff --git a/src/views/mayo.rs b/src/views/mayo.rs index 0595fde..2d9b45e 100644 --- a/src/views/mayo.rs +++ b/src/views/mayo.rs @@ -9,7 +9,7 @@ use crate::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Views as _, ms}; +use multi_sig::{ViewBuilder, ms}; use pq_mayo::{KeyPair, Mayo1, Mayo2, Mayo3, Mayo5, Signature, VerifyingKey}; use ssh_encoding::{Decode, Encode}; use zeroize::Zeroizing; @@ -350,7 +350,7 @@ impl<'a> VerifyView for View<'a> { kd.key_bytes()? }; - let sv = sig.data_view()?; + let sv = ViewBuilder::new(sig).data().build()?; let sig_bytes = sv.sig_bytes()?; match (key_bytes.len(), sig_bytes.len()) { diff --git a/src/views/ml_dsa.rs b/src/views/ml_dsa.rs index d7cb0cc..18ba475 100644 --- a/src/views/ml_dsa.rs +++ b/src/views/ml_dsa.rs @@ -14,7 +14,7 @@ use ml_dsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Views as _, ms}; +use multi_sig::{ViewBuilder, ms}; use ssh_encoding::{Decode, Encode}; use zeroize::Zeroizing; @@ -315,7 +315,7 @@ impl<'a> VerifyView for View<'a> { kd.key_bytes()? }; - let sv = sig.data_view()?; + let sv = ViewBuilder::new(sig).data().build()?; let sig_bytes = sv.sig_bytes()?; match (key_bytes.len(), sig_bytes.len()) { diff --git a/src/views/nist_p.rs b/src/views/nist_p.rs index faa1613..ef37da9 100644 --- a/src/views/nist_p.rs +++ b/src/views/nist_p.rs @@ -17,7 +17,7 @@ use elliptic_curve::Generate; use elliptic_curve::sec1::ToSec1Point; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use multi_trait::TryDecodeFrom; use multi_util::Varbytes; use multi_util::Varuint; @@ -400,7 +400,7 @@ impl<'a> VerifyView for View<'a> { kd.key_bytes()? }; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let msg = if let Some(msg) = msg { diff --git a/src/views/rsa.rs b/src/views/rsa.rs index cac9c44..fd4bc0e 100644 --- a/src/views/rsa.rs +++ b/src/views/rsa.rs @@ -21,7 +21,7 @@ use ::sad_rsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use multi_trait::TryDecodeFrom; use multi_util::{Varbytes, Varuint}; use ssh_encoding::{Decode, Encode}; @@ -401,7 +401,7 @@ impl<'a> VerifyView for View<'a> { let public_key = RsaPublicKey::from_pkcs1_der(&key_bytes) .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; let msg = if let Some(msg) = msg { diff --git a/src/views/secp256k1.rs b/src/views/secp256k1.rs index ef41b8b..6042440 100644 --- a/src/views/secp256k1.rs +++ b/src/views/secp256k1.rs @@ -19,7 +19,7 @@ use k256::ecdsa::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use multi_trait::TryDecodeFrom; use multi_util::{Varbytes, Varuint}; use ssh_encoding::{Decode, Encode}; @@ -355,7 +355,7 @@ impl<'a> VerifyView for View<'a> { .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; // get the signature data - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; // create the signature diff --git a/src/views/slh_dsa.rs b/src/views/slh_dsa.rs index a90f26e..cf15d38 100644 --- a/src/views/slh_dsa.rs +++ b/src/views/slh_dsa.rs @@ -11,7 +11,7 @@ use crate::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::Views as _; +use multi_sig::ViewBuilder; use multi_sig::ms; use slh_dsa::ParameterSet; use slh_dsa::signature::{Keypair, Signer, Verifier}; @@ -522,7 +522,7 @@ impl<'a> VerifyView for View<'a> { kd.key_bytes()? }; - let sv = sig.data_view()?; + let sv = ViewBuilder::new(sig).data().build()?; let sig_bytes = sv.sig_bytes()?; match self.mk.codec { diff --git a/src/views/xeddsa.rs b/src/views/xeddsa.rs index e6c6a42..21f8efa 100644 --- a/src/views/xeddsa.rs +++ b/src/views/xeddsa.rs @@ -31,7 +31,7 @@ use curve25519_dalek::{edwards::EdwardsPoint, montgomery::MontgomeryPoint, scala use ed25519_dalek::{Signature, Verifier, VerifyingKey}; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Multisig, Views as SigViews, ms}; +use multi_sig::{Multisig, ViewBuilder, ms}; use sha2::{Digest, Sha512}; use subtle::ConstantTimeEq; use zeroize::Zeroizing; @@ -363,7 +363,7 @@ impl<'a> VerifyView for View<'a> { let verifying_key = VerifyingKey::from_bytes(&verifying_key_bytes) .map_err(|e| ConversionsError::PublicKeyFailure(e.to_string()))?; - let sv = multisig.data_view()?; + let sv = ViewBuilder::new(multisig).data().build()?; let sig = sv.sig_bytes().map_err(|_| VerifyError::MissingSignature)?; if sig.len() != ED25519_SIGNATURE_LENGTH { return Err(VerifyError::BadSignature( @@ -401,6 +401,7 @@ impl<'a> VerifyView for View<'a> { mod tests { use super::*; use crate::{Builder, ViewBuilder}; + use multi_sig::ViewBuilder as SigViewBuilder; fn key_pair_mks() -> (Multikey, Multikey) { let mut rng = rand::rng(); @@ -518,7 +519,7 @@ mod tests { .unwrap() .sign(&msg, false, None) .unwrap(); - let view = sig.data_view().unwrap(); + let view = SigViewBuilder::new(&sig).data().build().unwrap(); let mut bytes = view.sig_bytes().unwrap(); bytes[0] ^= 1; let tampered = ms::Builder::new(Codec::XeddsaMsig) @@ -593,7 +594,7 @@ mod tests { .unwrap(); // Every signature is 64 bytes of R || s. - let dv = sig.data_view().unwrap(); + let dv = SigViewBuilder::new(&sig).data().build().unwrap(); assert_eq!(dv.sig_bytes().unwrap().len(), 64); let _ = a; } diff --git a/src/views/xmss.rs b/src/views/xmss.rs index dacbbb0..2d8e2f9 100644 --- a/src/views/xmss.rs +++ b/src/views/xmss.rs @@ -21,7 +21,7 @@ use crate::{ }; use multi_codec::Codec; use multi_hash::{Multihash, mh}; -use multi_sig::{Views as _, ms}; +use multi_sig::{ViewBuilder, ms}; use zeroize::Zeroizing; // ---- Inlined bs-xmss wrapper logic ---- @@ -389,7 +389,7 @@ impl<'a> VerifyView for View<'a> { let kd = dispatch_data_view(&pubmk)?; kd.key_bytes()? }; - let sv = sig.data_view()?; + let sv = ViewBuilder::new(sig).data().build()?; let sig_bytes = sv.sig_bytes()?; verify_bytes(pubmk.codec, key_bytes.as_slice(), &sig_bytes, msg_bytes) diff --git a/tests/merkle_lamport_tests.rs b/tests/merkle_lamport_tests.rs index 29128a2..b877738 100644 --- a/tests/merkle_lamport_tests.rs +++ b/tests/merkle_lamport_tests.rs @@ -6,7 +6,7 @@ #![allow(clippy::uninlined_format_args)] use multi_codec::Codec; use multi_key::{Builder, Multikey, ViewBuilder}; -use multi_sig::{Multisig, Views as _}; +use multi_sig::{Multisig, ViewBuilder as SigViewBuilder}; #[test] fn test_merkle_sign_advance_and_verify() { @@ -106,12 +106,22 @@ fn test_merkle_threshold_split_sign_combine_verify() { .try_build() .unwrap(); for share in &sig_shares { - let next = acc.threshold_view().unwrap().add_share(share).unwrap(); + let next = SigViewBuilder::new(&acc) + .threshold() + .build() + .unwrap() + .add_share(share) + .unwrap(); acc = next; } assert_eq!(acc.depth(), Some(1)); - let combined = acc.threshold_view().unwrap().combine().unwrap(); + let combined = SigViewBuilder::new(&acc) + .threshold() + .build() + .unwrap() + .combine() + .unwrap(); assert_eq!(combined.depth(), Some(1)); // verify under the tree-root public key From 7cd53442eff417d12762f055c0e6645c7fc5d4fc Mon Sep 17 00:00:00 2001 From: Dave Grantham Date: Wed, 7 Oct 2026 21:14:33 -0600 Subject: [PATCH 2/2] release metadata Signed-off-by: Dave Grantham --- CHANGELOG.md | 7 +++++++ Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55458c2..57a275f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.1.1] - 2026-10-07 + +### Changed + +- Migrated internal `Multisig` view construction from `multi_sig::Views` to `multi_sig::ViewBuilder`. Requirement `multi-sig` raised 1.4 → 1.5. No public API changes. + ## [2.1.0] - 2026-10-07 ### Added @@ -259,6 +265,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Major dependency updates: ed25519-dalek 3, blsful 4, elliptic-curve 0.14, vsss-rs 6, ssh-key 0.7. - Initial published release on crates.io as `multi-key`. +[2.1.1]: https://github.com/cryptidtech/multi-key/compare/v2.1.0...v2.1.1 [2.1.0]: https://github.com/cryptidtech/multi-key/compare/v2.0.0...v2.1.0 [1.1.1]: https://github.com/cryptidtech/multi-key/compare/v1.1.0...v1.1.1 [1.2.2]: https://github.com/cryptidtech/multi-key/compare/v1.2.1...v1.2.2 diff --git a/Cargo.toml b/Cargo.toml index bfb748c..ce01927 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-key" -version = "2.1.0" +version = "2.1.1" edition = "2024" rust-version = "1.96" authors = ["Dave Grantham "]