diff --git a/CHANGELOG.md b/CHANGELOG.md index f487021d3..23ecb0988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Added `orchard::keys::FullViewingKey::from_sk_and_ak` under the +`unstable-frost` feature flag +- Added `orchard::keys::FullViewingKey::from_checked_parts` under the +`unstable-frost` feature flag ## [0.9.1] - 2024-08-13 @@ -19,6 +23,18 @@ and this project adheres to Rust's notion of `unstable-frost` feature flag. These are temporary APIs exposed for development purposes, and will be replaced by type-safe FROST APIs once ZIP 312 key generation is specified (https://github.com/zcash/zips/pull/883). +- `orchard::keys::SpendValidatingKey` exposes its composing parts through functions +gated by the `unstable-frost` feature flag. These functions are intended to be used +by FROST clients to backup the key elements. +- `orchard::keys::NullifierDerivingKey::from_bytes` made `pub` behind the +`unstable-frost` feature flag. +- `orchard::keys::NullifierDerivingKey::to_bytes` made `pub` behind the +`unstable-frost` feature flag. +- `orchard::keys::CommitIvkRandomness::from_bytes` made `pub` behind the +`unstable-frost` feature flag. +- `orchard::keys::CommitIvkRandomness::to_bytes` made `pub` behind the +`unstable-frost` feature flag. + ### Changed - Migrated to `incrementalmerkletree 0.6`, `bridgetree 0.5`. diff --git a/src/keys.rs b/src/keys.rs index f66928eeb..5c99f466b 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -225,6 +225,7 @@ impl SpendValidatingKey { /// [`Note`]: crate::note::Note /// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents #[derive(Copy, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) struct NullifierDerivingKey(pallas::Base); impl NullifierDerivingKey { @@ -245,10 +246,13 @@ impl NullifierDerivingKey { } /// Converts this nullifier deriving key to its serialized form. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn to_bytes(self) -> [u8; 32] { <[u8; 32]>::from(self.0) } + /// Converts this nullifier deriving key from its serialized form. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn from_bytes(bytes: &[u8]) -> Option { let nk_bytes = <[u8; 32]>::try_from(bytes).ok()?; let nk = pallas::Base::from_repr(nk_bytes).map(NullifierDerivingKey); @@ -266,6 +270,7 @@ impl NullifierDerivingKey { /// /// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents #[derive(Copy, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) struct CommitIvkRandomness(pallas::Scalar); impl From<&SpendingKey> for CommitIvkRandomness { @@ -279,11 +284,14 @@ impl CommitIvkRandomness { self.0 } - /// Converts this nullifier deriving key to its serialized form. + /// Converts this [`CommitIvkRandomness`] to its serialized form. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn to_bytes(self) -> [u8; 32] { <[u8; 32]>::from(self.0) } + /// Converts this [`CommitIvkRandomness`] from its serialized form. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn from_bytes(bytes: &[u8]) -> Option { let rivk_bytes = <[u8; 32]>::try_from(bytes).ok()?; let rivk = pallas::Scalar::from_repr(rivk_bytes).map(CommitIvkRandomness); @@ -333,11 +341,47 @@ impl From for SpendValidatingKey { } impl FullViewingKey { + /// Creates a `FullViewingKey` from a `SpendingKey` and `SpendValidatingKey`. + /// This is necessary for FROST key management. + #[cfg(feature = "unstable-frost")] + pub fn from_sk_and_ak(sk: &SpendingKey, ak: SpendValidatingKey) -> FullViewingKey { + FullViewingKey { + ak, + nk: NullifierDerivingKey::from(sk), + rivk: CommitIvkRandomness::from(sk), + } + } + + /// Creates a `FullViewingKey` from its checked parts. This is necessary for FROST + /// key management in order to avoid centralizing spend authority in a backup scheme. + #[cfg(feature = "unstable-frost")] + pub fn from_checked_parts( + ak: SpendValidatingKey, + nk: NullifierDerivingKey, + rivk: CommitIvkRandomness, + ) -> FullViewingKey { + FullViewingKey { ak, nk, rivk } + } + + /// Returns the `SpendValidatingKey` of this `FullViewingKey` + /// - Note: this is intended for the "unstable-frost" feature to + /// facilitate the DKG'd key backup scheme. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] + pub fn ak(&self) -> &SpendValidatingKey { + &self.ak + } + /// Returns the `NullifierDerivingKey` of this `FullViewingKey` + /// - Note: this is `pub` for the "unstable-frost" feature to + /// facilitate the DKG'd key backup scheme. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn nk(&self) -> &NullifierDerivingKey { &self.nk } /// Returns either `rivk` or `rivk_internal` based on `scope`. + /// - Note: this is `pub` for the "unstable-frost" feature to + /// facilitate the DKG'd key backup scheme. + #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn rivk(&self, scope: Scope) -> CommitIvkRandomness { match scope { Scope::External => self.rivk,