adopt BIP-340 for all Secp256k1 networks in EXODUS

Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
Uncle Stretch 2026-09-09 03:41:28 +03:00
parent a6e87c20d6
commit fd8e52b520
Signed by: str3tch
GPG Key ID: 84F3190747EE79AA
10 changed files with 116 additions and 110 deletions

10
Cargo.lock generated
View File

@ -3363,10 +3363,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "frost-secp256k1" name = "frost-secp256k1-tr"
version = "2.2.0" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f6974379aee791f2f9e0db47c37d9e4c77ea8a8233e488ae8949ce4c6864e96" checksum = "ff8a25b14bfd5d25deba5edce61ec99c3afb752a1d26630a196bba4cb1c4ca5e"
dependencies = [ dependencies = [
"document-features", "document-features",
"frost-core", "frost-core",
@ -3684,7 +3684,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-exodus" name = "ghost-exodus"
version = "0.0.8" version = "0.0.9"
dependencies = [ dependencies = [
"chacha20poly1305", "chacha20poly1305",
"frame-benchmarking", "frame-benchmarking",
@ -3693,7 +3693,7 @@ dependencies = [
"frame-system", "frame-system",
"frost-core", "frost-core",
"frost-ed25519", "frost-ed25519",
"frost-secp256k1", "frost-secp256k1-tr",
"ghost-helpers", "ghost-helpers",
"ghost-networks", "ghost-networks",
"ghost-traits", "ghost-traits",
@ -4085,7 +4085,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-traits" name = "ghost-traits"
version = "0.4.5" version = "0.4.6"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"frost-core", "frost-core",

View File

@ -89,7 +89,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features =
scale-info = { version = "2.5.0", default-features = false } scale-info = { version = "2.5.0", default-features = false }
subxt = { version = "0.37.0", default-features = false } subxt = { version = "0.37.0", default-features = false }
frost-secp256k1 = { version = "2.2.0", default-features = false, features = ["serialization"] } frost-secp256k1-tr = { version = "2.2.0", default-features = false, features = ["serialization"] }
frost-ed25519 = { version = "2.2.0", default-features = false, features = ["serialization"] } frost-ed25519 = { version = "2.2.0", default-features = false, features = ["serialization"] }
chacha20poly1305 = { version = "0.10.1", default-features = false, features = ["alloc"] } chacha20poly1305 = { version = "0.10.1", default-features = false, features = ["alloc"] }
frost-core = { version = "2.2.0", default-features = false } frost-core = { version = "2.2.0", default-features = false }
@ -345,7 +345,7 @@ curve25519-dalek = { opt-level = 3 }
ed25519-dalek = { opt-level = 3 } ed25519-dalek = { opt-level = 3 }
flate2 = { opt-level = 3 } flate2 = { opt-level = 3 }
frost-core = { opt-level = 3 } frost-core = { opt-level = 3 }
frost-secp256k1 = { opt-level = 3 } frost-secp256k1-tr = { opt-level = 3 }
futures-channel = { opt-level = 3 } futures-channel = { opt-level = 3 }
hash-db = { opt-level = 3 } hash-db = { opt-level = 3 }
hashbrown = { opt-level = 3 } hashbrown = { opt-level = 3 }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-exodus" name = "ghost-exodus"
version = "0.0.8" version = "0.0.9"
description = "Threshold signature generation with DKG included" description = "Threshold signature generation with DKG included"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true
@ -28,7 +28,7 @@ sp-core = { workspace = true }
sp-std = { workspace = true } sp-std = { workspace = true }
sp-io = { workspace = true } sp-io = { workspace = true }
frost-secp256k1 = { workspace = true } frost-secp256k1-tr = { workspace = true }
frost-ed25519 = { workspace = true } frost-ed25519 = { workspace = true }
frost-core = { workspace = true } frost-core = { workspace = true }
rand_chacha = { workspace = true } rand_chacha = { workspace = true }
@ -75,7 +75,7 @@ std = [
"sp-core/std", "sp-core/std",
"sp-std/std", "sp-std/std",
"sp-io/std", "sp-io/std",
"frost-secp256k1/std", "frost-secp256k1-tr/std",
"frost-ed25519/std", "frost-ed25519/std",
"frost-core/std", "frost-core/std",
"ghost-traits/std", "ghost-traits/std",

View File

@ -285,6 +285,9 @@ impl DistributedKeyGeneration<AuthIndex, ExodusError> for NetworkCurve {
_ => ExodusError::Unknown, _ => ExodusError::Unknown,
})?; })?;
let key_package = key_package.normalize_package();
let pubkey_package = pubkey_package.normalize_package();
let key_package_bytes = key_package.serialize() let key_package_bytes = key_package.serialize()
.map_err(|_| ExodusError::SerializationError)?; .map_err(|_| ExodusError::SerializationError)?;
@ -337,15 +340,4 @@ impl DistributedKeyGeneration<AuthIndex, ExodusError> for NetworkCurve {
.map_err(|_| ExodusError::SerializationError) .map_err(|_| ExodusError::SerializationError)
}) })
} }
fn dkg_decompress_key(
&self,
verifying_key_bytes: &[u8],
) -> Result<Vec<u8>, ExodusError> {
with_ciphersuite!(self, |f| {
let verifying_key = f::VerifyingKey::deserialize(verifying_key_bytes)
.map_err(|_| ExodusError::DeserializationError)?;
decomporess_key(verifying_key)
})
}
} }

View File

@ -17,6 +17,13 @@ impl FlexibleRoundOptimizedSchnorrThresholdSignature<AuthIndex, ExodusError> for
fn header_bytes_len(&self) -> usize { 5 } fn header_bytes_len(&self) -> usize { 5 }
fn signature_bytes_len(&self) -> usize {
match self {
NetworkCurve::Secp256k1 => 64,
NetworkCurve::Ed25519 => 64,
}
}
fn element_bytes_len(&self) -> usize { fn element_bytes_len(&self) -> usize {
match self { match self {
NetworkCurve::Secp256k1 => 33, NetworkCurve::Secp256k1 => 33,
@ -76,7 +83,7 @@ impl FlexibleRoundOptimizedSchnorrThresholdSignature<AuthIndex, ExodusError> for
<InnerGroup as frost_core::Group>::Serialization::try_from(group_commitment_bytes.as_ref()) <InnerGroup as frost_core::Group>::Serialization::try_from(group_commitment_bytes.as_ref())
.map_err(|_| ExodusError::DeserializationError)?; .map_err(|_| ExodusError::DeserializationError)?;
let group_commitment_element = let mut group_commitment_element =
<InnerGroup as frost_core::Group>::deserialize(&group_commitment_serialization) <InnerGroup as frost_core::Group>::deserialize(&group_commitment_serialization)
.map_err(|_| ExodusError::DeserializationError)?; .map_err(|_| ExodusError::DeserializationError)?;
@ -95,15 +102,6 @@ impl FlexibleRoundOptimizedSchnorrThresholdSignature<AuthIndex, ExodusError> for
let verifying_key = f::VerifyingKey::deserialize(verifying_key_bytes) let verifying_key = f::VerifyingKey::deserialize(verifying_key_bytes)
.map_err(|_| ExodusError::DeserializationError)?; .map_err(|_| ExodusError::DeserializationError)?;
let challenge = frost_core::challenge(
&group_commitment_element,
&verifying_key,
message,
).map_err(|err| match err {
f::Error::SerializationError => ExodusError::SerializationError,
_ => ExodusError::Unknown,
})?;
let hiding_element_serialization = let hiding_element_serialization =
<InnerGroup as frost_core::Group>::Serialization::try_from(nonce_hiding_bytes.as_ref()) <InnerGroup as frost_core::Group>::Serialization::try_from(nonce_hiding_bytes.as_ref())
.map_err(|_| ExodusError::DeserializationError)?; .map_err(|_| ExodusError::DeserializationError)?;
@ -120,7 +118,25 @@ impl FlexibleRoundOptimizedSchnorrThresholdSignature<AuthIndex, ExodusError> for
<InnerGroup as frost_core::Group>::deserialize(&binding_element_serialization) <InnerGroup as frost_core::Group>::deserialize(&binding_element_serialization)
.map_err(|_| ExodusError::DeserializationError)?; .map_err(|_| ExodusError::DeserializationError)?;
let r_i_element = hiding_element + (binding_element * binding_factor_scalar); let mut r_i_element = hiding_element + (binding_element * binding_factor_scalar);
let group_commitment_wrapper =
frost_core::GroupCommitment::<Ciphersuite>::from_element(group_commitment_element);
if !group_commitment_wrapper.is_normalized() {
r_i_element = -r_i_element;
group_commitment_element = -group_commitment_element;
}
let challenge = <Ciphersuite as frost_core::Ciphersuite>::challenge(
&group_commitment_element,
&verifying_key,
message,
).map_err(|err| match err {
f::Error::SerializationError => ExodusError::SerializationError,
_ => ExodusError::Unknown,
})?;
let commitment_share = let commitment_share =
frost_core::round1::GroupCommitmentShare::from_element(r_i_element); frost_core::round1::GroupCommitmentShare::from_element(r_i_element);
@ -275,14 +291,14 @@ impl FlexibleRoundOptimizedSchnorrThresholdSignature<AuthIndex, ExodusError> for
let signing_package = f::SigningPackage::new(signing_commitments, message); let signing_package = f::SigningPackage::new(signing_commitments, message);
let binding_factors_list_wrapped = let binding_factors_list_wrapped =
frost_core::compute_binding_factor_list(&signing_package, &verifying_key, &[]) frost_core::compute_binding_factor_list::<Ciphersuite>(&signing_package, &verifying_key, &[])
.map_err(|err| match err { .map_err(|err| match err {
f::Error::SerializationError => ExodusError::SerializationError, f::Error::SerializationError => ExodusError::SerializationError,
_ => ExodusError::Unknown, _ => ExodusError::Unknown,
})?; })?;
let group_commitment = let group_commitment =
frost_core::compute_group_commitment(&signing_package, &binding_factors_list_wrapped) frost_core::compute_group_commitment::<Ciphersuite>(&signing_package, &binding_factors_list_wrapped)
.map_err(|err| match err { .map_err(|err| match err {
f::Error::IdentityCommitment => ExodusError::IdentityCommitment, f::Error::IdentityCommitment => ExodusError::IdentityCommitment,
f::Error::UnknownIdentifier => ExodusError::UnknownIdentifier, f::Error::UnknownIdentifier => ExodusError::UnknownIdentifier,

View File

@ -3,46 +3,53 @@ macro_rules! with_ciphersuite {
($curve:expr, |$alias:ident| $body:block) => { ($curve:expr, |$alias:ident| $body:block) => {
match $curve { match $curve {
NetworkCurve::Secp256k1 => { NetworkCurve::Secp256k1 => {
use k256::elliptic_curve::sec1::ToEncodedPoint; #[allow(unused_imports)]
use frost_secp256k1 as $alias; use frost_secp256k1_tr as $alias;
#[allow(unused_imports)] #[allow(unused_imports)]
use frost_secp256k1::Secp256K1Sha256 as Ciphersuite; use frost_secp256k1_tr::Secp256K1Sha256TR as Ciphersuite;
use $alias::keys::EvenY;
#[allow(dead_code)] #[allow(dead_code)]
fn decomporess_key( trait UniversalNormalizer {
verifying_key: $alias::VerifyingKey, fn normalize_package(self) -> Self;
) -> Result<Vec<u8>, ExodusError> { fn is_normalized(&self) -> bool;
let element = verifying_key.to_element();
if element == k256::ProjectivePoint::IDENTITY {
return Err(ExodusError::InvalidIdentityElement);
} }
let mut fixed_serialized = [0; 65]; impl<T: EvenY> UniversalNormalizer for T {
let serialized_point = element.to_affine().to_encoded_point(false); #[inline]
let serialized = serialized_point.as_bytes(); fn normalize_package(self) -> Self {
fixed_serialized.copy_from_slice(serialized); self.into_even_y(None)
}
Ok(fixed_serialized.to_vec()) #[inline]
fn is_normalized(&self) -> bool {
self.has_even_y()
}
} }
$body $body
}, },
NetworkCurve::Ed25519 => { NetworkCurve::Ed25519 => {
#[allow(unused_imports)]
use frost_ed25519 as $alias; use frost_ed25519 as $alias;
#[allow(unused_imports)] #[allow(unused_imports)]
use frost_ed25519::Ed25519Sha512 as Ciphersuite; use frost_ed25519::Ed25519Sha512 as Ciphersuite;
#[allow(dead_code)] #[allow(dead_code)]
fn decomporess_key( trait UniversalNormalizer {
verifying_key: $alias::VerifyingKey, fn normalize_package(self) -> Self;
) -> Result<Vec<u8>, ExodusError> { fn is_normalized(&self) -> bool;
verifying_key.serialize().map_err(|err| match err { }
f::Error::SerializationError => ExodusError::SerializationError,
_ => ExodusError::Unknown, impl<T> UniversalNormalizer for T {
}) #[inline]
fn normalize_package(self) -> Self { self }
#[inline]
fn is_normalized(&self) -> bool { true }
} }
$body $body

View File

@ -130,26 +130,17 @@ const fn postcard_varint_len(len: usize) -> usize {
else { 3 } else { 3 }
} }
const fn signature_bytes_len(
element_bytes_len: usize,
scalar_bytes_len: usize,
)-> usize {
let signature_bytes_len = element_bytes_len.saturating_add(scalar_bytes_len);
let signature_vec_prefix = postcard_varint_len(signature_bytes_len);
signature_bytes_len.saturating_add(signature_vec_prefix)
}
const fn round1_package_size( const fn round1_package_size(
commitments_count: usize, commitments_count: usize,
element_bytes_len: usize, element_bytes_len: usize,
scalar_bytes_len: usize, signature_bytes_len: usize,
header_bytes_len: usize header_bytes_len: usize
) -> usize { ) -> usize {
let commitments_bytes_len = commitments_count.saturating_mul(element_bytes_len); let commitments_bytes_len = commitments_count.saturating_mul(element_bytes_len);
let commitment_vec_prefix = postcard_varint_len(commitments_count); let commitment_vec_prefix = postcard_varint_len(commitments_count);
signature_bytes_len(element_bytes_len, scalar_bytes_len) postcard_varint_len(signature_bytes_len)
.saturating_add(signature_bytes_len)
.saturating_add(header_bytes_len) .saturating_add(header_bytes_len)
.saturating_add(commitment_vec_prefix) .saturating_add(commitment_vec_prefix)
.saturating_add(commitments_bytes_len) .saturating_add(commitments_bytes_len)
@ -264,11 +255,12 @@ impl<T: Config> Get<u32> for Round1MaxBytes<T> {
fn get() -> u32 { fn get() -> u32 {
let max_authorities = T::MaxAuthorities::get(); let max_authorities = T::MaxAuthorities::get();
let min_authorities = get_byzantium_quorum_threshold(max_authorities); let min_authorities = get_byzantium_quorum_threshold(max_authorities);
let max_signature_bytes = ELEMENT_MAX_BYTES + SCALAR_MAX_BYTES;
round1_package_size( round1_package_size(
min_authorities as usize, min_authorities as usize,
ELEMENT_MAX_BYTES as usize, ELEMENT_MAX_BYTES as usize,
SCALAR_MAX_BYTES as usize, max_signature_bytes as usize,
HEADER_MAX_BYTES as usize, HEADER_MAX_BYTES as usize,
) as u32 ) as u32
} }
@ -363,10 +355,8 @@ impl<T: Config> Get<u32> for SignatureShareMaxBytes<T> {
pub struct SignatureMaxBytes<T>(sp_std::marker::PhantomData<T>); pub struct SignatureMaxBytes<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Get<u32> for SignatureMaxBytes<T> { impl<T: Config> Get<u32> for SignatureMaxBytes<T> {
fn get() -> u32 { fn get() -> u32 {
signature_bytes_len( let signature_max_bytes = ELEMENT_MAX_BYTES + SCALAR_MAX_BYTES;
ELEMENT_MAX_BYTES as usize, postcard_varint_len(signature_max_bytes as usize) as u32
SCALAR_MAX_BYTES as usize,
) as u32
} }
} }
@ -2533,6 +2523,7 @@ impl<T: Config> Pallet<T> {
dkg_qualification.intersect_indexes(&participants); dkg_qualification.intersect_indexes(&participants);
if dkg_qualification.count_ones::<AuthIndex>() < min_threshold { if dkg_qualification.count_ones::<AuthIndex>() < min_threshold {
dkg_qualification.nullify_indexes(); dkg_qualification.nullify_indexes();
return; return;
@ -2716,7 +2707,7 @@ impl<T: Config> Pallet<T> {
let expected_package_len = round1_package_size( let expected_package_len = round1_package_size(
expected_count, expected_count,
network_curve.element_bytes_len(), network_curve.element_bytes_len(),
network_curve.scalar_bytes_len(), network_curve.signature_bytes_len(),
network_curve.header_bytes_len(), network_curve.header_bytes_len(),
); );

View File

@ -15,8 +15,8 @@ use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng; use rand_chacha::ChaCha20Rng;
use frost_core::Field; use frost_core::Field;
use frost_secp256k1::{ use frost_secp256k1_tr::{
Secp256K1Sha256, Secp256K1ScalarField, Identifier as Secp256K1Identifier, Secp256K1Sha256TR, Secp256K1ScalarField, Identifier as Secp256K1Identifier,
keys::{ keys::{
VerifyingShare as Secp256K1VerifyingShare, VerifyingShare as Secp256K1VerifyingShare,
SigningShare as Secp256K1SigningShare, SigningShare as Secp256K1SigningShare,
@ -1452,7 +1452,7 @@ fn test_merkle_tree_success_power_of_two_for_shares() {
let indices = (1..=32).collect::<Vec<AuthIndex>>(); let indices = (1..=32).collect::<Vec<AuthIndex>>();
let shares = generate_mock_secp256k1_shares(&indices); let shares = generate_mock_secp256k1_shares(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
|share| share.serialize().map_err(|_| ExodusError::SerializationError), |share| share.serialize().map_err(|_| ExodusError::SerializationError),
).unwrap(); ).unwrap();
@ -1465,7 +1465,7 @@ fn test_merkle_tree_success_power_of_two_for_shares() {
).unwrap(); ).unwrap();
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
&tree, &tree,
auth_index, auth_index,
@ -1489,7 +1489,7 @@ fn test_merkle_tree_success_power_of_two_for_scalar() {
let indices = (1..=32).collect::<Vec<AuthIndex>>(); let indices = (1..=32).collect::<Vec<AuthIndex>>();
let scalars = generate_mock_secp256k1_scalars(&indices); let scalars = generate_mock_secp256k1_scalars(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
|scalar| { |scalar| {
let serialized = <Secp256K1ScalarField as Field>::serialize(scalar); let serialized = <Secp256K1ScalarField as Field>::serialize(scalar);
@ -1505,7 +1505,7 @@ fn test_merkle_tree_success_power_of_two_for_scalar() {
).unwrap(); ).unwrap();
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
&tree, &tree,
auth_index, auth_index,
@ -1538,7 +1538,7 @@ fn test_random_sparse_combinations_stress_for_shares() {
let indices: Vec<AuthIndex> = unique_indices.into_iter().collect(); let indices: Vec<AuthIndex> = unique_indices.into_iter().collect();
let shares = generate_mock_secp256k1_shares(&indices); let shares = generate_mock_secp256k1_shares(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
|share| share.serialize().map_err(|_| ExodusError::SerializationError), |share| share.serialize().map_err(|_| ExodusError::SerializationError),
).unwrap(); ).unwrap();
@ -1547,7 +1547,7 @@ fn test_random_sparse_combinations_stress_for_shares() {
for &auth_index in &indices { for &auth_index in &indices {
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
&tree, &tree,
auth_index, auth_index,
@ -1576,7 +1576,7 @@ fn test_random_sparse_combinations_stress_for_scalars() {
let indices: Vec<AuthIndex> = unique_indices.into_iter().collect(); let indices: Vec<AuthIndex> = unique_indices.into_iter().collect();
let scalars = generate_mock_secp256k1_scalars(&indices); let scalars = generate_mock_secp256k1_scalars(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
|scalar| { |scalar| {
let serialized = <Secp256K1ScalarField as Field>::serialize(scalar); let serialized = <Secp256K1ScalarField as Field>::serialize(scalar);
@ -1588,7 +1588,7 @@ fn test_random_sparse_combinations_stress_for_scalars() {
for &auth_index in &indices { for &auth_index in &indices {
let (scalars_bytes, proof) = let (scalars_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
&tree, &tree,
auth_index, auth_index,
@ -1614,7 +1614,7 @@ fn test_participants_with_high_index_gap_for_shares() {
let indices = vec![1, 1023]; let indices = vec![1, 1023];
let shares = generate_mock_secp256k1_shares(&indices); let shares = generate_mock_secp256k1_shares(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
|share| share.serialize().map_err(|_| ExodusError::SerializationError), |share| share.serialize().map_err(|_| ExodusError::SerializationError),
).unwrap(); ).unwrap();
@ -1622,7 +1622,7 @@ fn test_participants_with_high_index_gap_for_shares() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
&tree, &tree,
1023, 1023,
@ -1646,7 +1646,7 @@ fn test_participants_with_high_index_gap_for_scalars() {
let indices = vec![1, 1023]; let indices = vec![1, 1023];
let scalars = generate_mock_secp256k1_scalars(&indices); let scalars = generate_mock_secp256k1_scalars(&indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
|scalar| { |scalar| {
let serialized = <Secp256K1ScalarField as Field>::serialize(scalar); let serialized = <Secp256K1ScalarField as Field>::serialize(scalar);
@ -1657,7 +1657,7 @@ fn test_participants_with_high_index_gap_for_scalars() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (scalars_bytes, proof) = let (scalars_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
&tree, &tree,
1023, 1023,
@ -1684,7 +1684,7 @@ fn test_regression_consecutive_vs_position_for_shares() {
let custom_indices = vec![2, 3]; let custom_indices = vec![2, 3];
let shares = generate_mock_secp256k1_shares(&custom_indices); let shares = generate_mock_secp256k1_shares(&custom_indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
|scalar| scalar.serialize().map_err(|_| ExodusError::SerializationError), |scalar| scalar.serialize().map_err(|_| ExodusError::SerializationError),
).unwrap(); ).unwrap();
@ -1692,7 +1692,7 @@ fn test_regression_consecutive_vs_position_for_shares() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
&tree, &tree,
2, 2,
@ -1709,7 +1709,7 @@ fn test_regression_consecutive_vs_position_for_scalars() {
let custom_indices = vec![2, 3]; let custom_indices = vec![2, 3];
let scalars = generate_mock_secp256k1_scalars(&custom_indices); let scalars = generate_mock_secp256k1_scalars(&custom_indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
|scalar| { |scalar| {
let serialized = <Secp256K1ScalarField as Field>::serialize(scalar); let serialized = <Secp256K1ScalarField as Field>::serialize(scalar);
@ -1720,7 +1720,7 @@ fn test_regression_consecutive_vs_position_for_scalars() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (scalars_bytes, proof) = let (scalars_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
&tree, &tree,
2, 2,
@ -1740,7 +1740,7 @@ fn test_attack_with_unknown_authority_index_for_shares() {
let custom_indices = vec![1, 2, 3]; let custom_indices = vec![1, 2, 3];
let shares = generate_mock_secp256k1_shares(&custom_indices); let shares = generate_mock_secp256k1_shares(&custom_indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
|scalar| scalar.serialize().map_err(|_| ExodusError::SerializationError), |scalar| scalar.serialize().map_err(|_| ExodusError::SerializationError),
).unwrap(); ).unwrap();
@ -1748,7 +1748,7 @@ fn test_attack_with_unknown_authority_index_for_shares() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (shares_bytes, proof) = let (shares_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&shares, &shares,
&tree, &tree,
2, 2,
@ -1765,7 +1765,7 @@ fn test_attack_with_unknown_authority_index_for_scalars() {
let custom_indices = vec![1, 2, 3]; let custom_indices = vec![1, 2, 3];
let scalars = generate_mock_secp256k1_scalars(&custom_indices); let scalars = generate_mock_secp256k1_scalars(&custom_indices);
let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256, _, _>( let tree = NetworkCurve::build_merkle_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
|scalar| { |scalar| {
let serialized = <Secp256K1ScalarField as Field>::serialize(scalar); let serialized = <Secp256K1ScalarField as Field>::serialize(scalar);
@ -1776,7 +1776,7 @@ fn test_attack_with_unknown_authority_index_for_scalars() {
let root = *tree.last().unwrap(); let root = *tree.last().unwrap();
let (scalars_bytes, proof) = let (scalars_bytes, proof) =
NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256, _, _>( NetworkCurve::generate_merkle_proof_from_tree::<Secp256K1Sha256TR, _, _>(
&scalars, &scalars,
&tree, &tree,
2, 2,
@ -2227,7 +2227,7 @@ fn curve_wrapper_for_dkg_works() {
#[test] #[test]
fn test_common_way_of_frost_usage() { fn test_common_way_of_frost_usage() {
use frost_secp256k1 as frost; use frost_secp256k1_tr as frost;
let mut rng = ChaCha20Rng::from_seed(Default::default()); let mut rng = ChaCha20Rng::from_seed(Default::default());

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-traits" name = "ghost-traits"
version = "0.4.5" version = "0.4.6"
description = "Shared traits including `GhostHasher`, `NetworkDataBasicHandler`, `BoundedBTreeMap`, `MerkleTree` and more." description = "Shared traits including `GhostHasher`, `NetworkDataBasicHandler`, `BoundedBTreeMap`, `MerkleTree` and more."
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -17,6 +17,7 @@ pub trait FlexibleRoundOptimizedSchnorrThresholdSignature<A, E>: MerkleTreeBuild
fn header_bytes_len(&self) -> usize; fn header_bytes_len(&self) -> usize;
fn element_bytes_len(&self) -> usize; fn element_bytes_len(&self) -> usize;
fn signature_bytes_len(&self) -> usize;
fn scalar_bytes_len(&self) -> usize; fn scalar_bytes_len(&self) -> usize;
fn verify_signature_share( fn verify_signature_share(
@ -84,7 +85,6 @@ pub trait DistributedKeyGeneration<A, E>: MerkleTreeBuilder<A, E> {
) -> Self::Part3Result; ) -> Self::Part3Result;
fn dkg_derive_verifying_share(&self, sk: &[u8]) -> Result<Vec<u8>, E>; fn dkg_derive_verifying_share(&self, sk: &[u8]) -> Result<Vec<u8>, E>;
fn dkg_decompress_key(&self, vk: &[u8]) -> Result<Vec<u8>, E>;
} }
pub trait MerkleTreeBuilder<A, E>: IdentifierConverter<A, E> { pub trait MerkleTreeBuilder<A, E>: IdentifierConverter<A, E> {