Conversation
- Adjust `&` handling in patterns
- Replaces custom deserialization code
- Use vec directly
- Infallible conversions - Disable arithmetic checks
- Use `assert!` over `debug_assert!` - Reference RFC when required
|
@claude Review |
|
Claude finished @emlautarom1's task in 7m 8s —— View job Code Review —
|
| /// | ||
| /// `ExpandMsgXmd(SHA-256, msg, DST, 48)` -> reverse bytes -> pad to 64 -> | ||
| /// `Scalar::from_bytes_wide`. | ||
| fn kryptology_hash_to_scalar(msg: &[u8]) -> Scalar { |
There was a problem hiding this comment.
It can be done without manually reversing:
fn kryptology_hash_to_scalar(msg: &[u8]) -> Scalar {
let xmd = expand_msg_xmd(msg, KRYPTOLOGY_DST, 48);
Scalar::from_be_bytes_wide(&xmd)
}
and new Scalar function needed:
/// Reduce big-endian bytes modulo the scalar field order.
pub(crate) fn from_be_bytes_wide(bytes: &[u8]) -> Self {
let mut scalar = blst_scalar::default();
let mut fr = blst_fr::default();
unsafe {
blst_scalar_from_be_bytes(&mut scalar, bytes.as_ptr(), bytes.len());
blst_fr_from_scalar(&mut fr, &scalar);
}
Scalar(fr)
}
| rng: &mut R, | ||
| ) -> Result<(Round1Bcast, BTreeMap<u32, ShamirShare>, Round1Secret), DkgError> { | ||
| // Kryptology encodes participant identifiers into a single byte. | ||
| if max_signers > u16::from(u8::MAX) { |
There was a problem hiding this comment.
Round1Secret::from_raw misses the validation logic (lines 282 - 290). What do you think about extracting it to the separate function and using in both places?
| BTreeMap::new(); | ||
| let mut share_sum = Scalar::ZERO; | ||
|
|
||
| for (&sender_id, bcast) in received_bcasts { |
There was a problem hiding this comment.
We could check secret.id == sender_id and return an error to prevent some wrong usage of the round2 function.
| /// The `id` must be the original 1-indexed kryptology participant ID. | ||
| pub fn from_key_package(id: u32, key_package: &KeyPackage, msg: &[u8]) -> BlsPartialSignature { | ||
| let scalar = key_package.signing_share().to_scalar(); | ||
| { |
| //! Contains the key material types (identifiers, shares, packages) and the | ||
| //! polynomial evaluation functions needed by the kryptology-compatible DKG. | ||
|
|
||
| #![allow(clippy::arithmetic_side_effects)] |
There was a problem hiding this comment.
Would be better to limit it to some specific scopes.
| //! The output types ([`KeyPackage`], [`PublicKeyPackage`]) are standard | ||
| //! frost-core types usable with frost-core's signing protocol. | ||
|
|
||
| #![allow(clippy::arithmetic_side_effects)] |
There was a problem hiding this comment.
Would be better to limit it to some specific scopes.
| impl Ord for Identifier { | ||
| /// Compare identifiers by their numeric scalar value, using big-endian byte | ||
| /// order. Serializes to little-endian, and compares in reverse order. | ||
| fn cmp(&self, other: &Self) -> Ordering { |
There was a problem hiding this comment.
This can be possibly optimized if we would keep u32 value at the construction time:
#[derive(Copy, Clone, Debug)]
pub struct Identifier {
id: u32,
scalar: Scalar,
}
impl Identifier {
pub fn from_u32(id: u32) -> Result<Self, FrostCoreError> {
let scalar = Scalar::from(u64::from(id));
if scalar == Scalar::ZERO {
Err(FrostCoreError::InvalidZeroScalar)
} else {
Ok(Self { id, scalar })
}
}
pub fn to_scalar(&self) -> Scalar {
self.scalar
}
}
impl Ord for Identifier {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
|
|
||
| /// Errors from the kryptology-compatible DKG. | ||
| #[derive(Debug)] | ||
| pub enum DkgError { |
There was a problem hiding this comment.
Would be nice to cover all errors with tests.
Partially resolves #254.
Based on https://github.com/ZcashFoundation/frost, we build a library implementing FROST compatible with Coinbase's Kryptology (https://github.com/coinbase/kryptology/blob/v1.8.0/pkg/dkg/frost/README.md). No new dependencies are added to the workspace.
I've created some custom Go test cases in Charon that are not part of this PR that generate some fixtures with intermediate values which gives us some initial confidence that we can interop with Go nodes. Still, full compatibility requires further attention.
This PR requires nuanced review due to the challenging cryptography aspects of the code.