From ee969a64a880d3e11a9cf48780a99bd20424a0d3 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 17 Mar 2021 17:17:01 +0800 Subject: [PATCH 1/8] Add Sinsemilla constants --- src/primitives/sinsemilla.rs | 11 ++++------- src/primitives/sinsemilla/constants.rs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 src/primitives/sinsemilla/constants.rs diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 9699f244..0e3a1e12 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -6,11 +6,8 @@ use pasta_curves::pallas; use crate::spec::extract_p; -const GROUP_HASH_Q: &str = "z.cash:SinsemillaQ"; -const GROUP_HASH_S: &str = "z.cash:SinsemillaS"; - -const K: usize = 10; -const C: usize = 253; +mod constants; +pub use constants::*; fn lebs2ip_k(bits: &[bool]) -> u32 { assert!(bits.len() == K); @@ -81,7 +78,7 @@ impl> Iterator for Pad { #[allow(non_snake_case)] fn Q(domain_prefix: &str) -> pallas::Point { - pallas::Point::hash_to_curve(GROUP_HASH_Q)(domain_prefix.as_bytes()) + pallas::Point::hash_to_curve(Q_PERSONALIZATION)(domain_prefix.as_bytes()) } /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. @@ -91,7 +88,7 @@ fn Q(domain_prefix: &str) -> pallas::Point { pub(crate) fn hash_to_point(domain_prefix: &str, msg: impl Iterator) -> pallas::Point { let padded: Vec<_> = Pad::new(msg).collect(); - let hasher_S = pallas::Point::hash_to_curve(GROUP_HASH_S); + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); padded diff --git a/src/primitives/sinsemilla/constants.rs b/src/primitives/sinsemilla/constants.rs new file mode 100644 index 00000000..beaa8c13 --- /dev/null +++ b/src/primitives/sinsemilla/constants.rs @@ -0,0 +1,17 @@ +//! Sinsemilla generators + +/// Number of bits of each message piece in SinsemillaHashToPoint +pub const K: usize = 10; + +/// The largest integer such that 2^c <= (r_P - 1) / 2, where r_P is the order +/// of Pallas. +pub const C: usize = 253; + +// Sinsemilla Q generators +/// SWU hash-to-curve personalization for Sinsemilla Q generators +pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ"; + +// Sinsemilla S generators + +/// SWU hash-to-curve personalization for Sinsemilla S generators +pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS"; From a3134e34c586b9328569ab3dd48715e72a20ffb6 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 17 Mar 2021 17:20:10 +0800 Subject: [PATCH 2/8] Introduce HashDomain and CommitDomain traits Co-authored-by: Jack Grigg --- src/primitives/sinsemilla.rs | 64 ++++++++++++++++++++++++++---------- src/spec.rs | 2 +- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 0e3a1e12..6a0b1fb0 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -76,16 +76,27 @@ impl> Iterator for Pad { } } -#[allow(non_snake_case)] -fn Q(domain_prefix: &str) -> pallas::Point { - pallas::Point::hash_to_curve(Q_PERSONALIZATION)(domain_prefix.as_bytes()) +pub trait HashDomain { + #[allow(non_snake_case)] + fn Q(&self) -> pallas::Point; +} + +pub struct Domain(pub &'static str); + +impl HashDomain for Domain { + fn Q(&self) -> pallas::Point { + pallas::Point::hash_to_curve(Q_PERSONALIZATION)(self.0.as_bytes()) + } } /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash #[allow(non_snake_case)] -pub(crate) fn hash_to_point(domain_prefix: &str, msg: impl Iterator) -> pallas::Point { +pub(crate) fn hash_to_point( + domain: &D, + msg: impl Iterator, +) -> pallas::Point { let padded: Vec<_> = Pad::new(msg).collect(); let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); @@ -93,42 +104,59 @@ pub(crate) fn hash_to_point(domain_prefix: &str, msg: impl Iterator padded .chunks(K) - .fold(Q(domain_prefix), |acc, chunk| acc.double() + S(chunk)) + .fold(domain.Q(), |acc, chunk| acc.double() + S(chunk)) } /// `SinsemillaHash` from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash -pub(crate) fn hash(domain_prefix: &str, msg: impl Iterator) -> pallas::Base { - extract_p(&hash_to_point(domain_prefix, msg)) +pub(crate) fn hash(domain: &D, msg: impl Iterator) -> pallas::Base { + extract_p(&hash_to_point(domain, msg)) +} + +pub trait CommitDomain: HashDomain { + #[allow(non_snake_case)] + fn R(&self) -> pallas::Point; +} + +pub struct Comm(pub &'static str); + +impl HashDomain for Comm { + fn Q(&self) -> pallas::Point { + let m_prefix = self.0.to_owned() + "-M"; + pallas::Point::hash_to_curve(Q_PERSONALIZATION)(m_prefix.as_bytes()) + } +} + +impl CommitDomain for Comm { + fn R(&self) -> pallas::Point { + let r_prefix = self.0.to_owned() + "-r"; + let hasher_r = pallas::Point::hash_to_curve(&r_prefix); + hasher_r(&[]) + } } /// `SinsemillaCommit` from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit #[allow(non_snake_case)] -pub(crate) fn commit( - domain_prefix: &str, +pub(crate) fn commit( + domain: &D, msg: impl Iterator, r: &pallas::Scalar, ) -> pallas::Point { - let m_prefix = domain_prefix.to_owned() + "-M"; - let r_prefix = domain_prefix.to_owned() + "-r"; - - let hasher_r = pallas::Point::hash_to_curve(&r_prefix); - - hash_to_point(&m_prefix, msg) + hasher_r(&[]) * r + hash_to_point(domain, msg) + domain.R() * r } /// `SinsemillaShortCommit` from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit -pub(crate) fn short_commit( - domain_prefix: &str, +pub(crate) fn short_commit( + domain: &D, msg: impl Iterator, r: &pallas::Scalar, ) -> pallas::Base { - extract_p(&commit(domain_prefix, msg, r)) + extract_p(&commit(domain, msg, r)) } #[cfg(test)] diff --git a/src/spec.rs b/src/spec.rs index b2445223..969ef331 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -41,7 +41,7 @@ pub(crate) fn commit_ivk( // We rely on the API contract that to_le_bits() returns at least PrimeField::NUM_BITS // bits, which is equal to L_ORCHARD_BASE. let ivk = sinsemilla::short_commit( - "z.cash:Orchard-CommitIvk", + &sinsemilla::Comm("z.cash:Orchard-CommitIvk"), iter::empty() .chain(ak.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)) .chain(nk.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)), From 946b50ebfe10686fdd41f7d49d41213c5e0845a3 Mon Sep 17 00:00:00 2001 From: ying tong Date: Thu, 18 Mar 2021 11:41:42 +0800 Subject: [PATCH 3/8] Add documentation Co-authored-by: str4d --- src/primitives/sinsemilla.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 6a0b1fb0..2a18f2f8 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -76,11 +76,21 @@ impl> Iterator for Pad { } } +/// Trait representing a domain in which [`sinsemilla::hash_to_point`] and +/// [`sinsemilla::hash`] can be used. +/// +/// [`sinsemilla::hash_to_point`]: self::hash_to_point +/// [`sinsemilla::hash`]: self::hash pub trait HashDomain { #[allow(non_snake_case)] fn Q(&self) -> pallas::Point; } +/// A domain with a specific prefix string, in which [`sinsemilla::hash_to_point`] and +/// [`sinsemilla::hash`] can be used. +/// +/// [`sinsemilla::hash_to_point`]: self::hash_to_point +/// [`sinsemilla::hash`]: self::hash pub struct Domain(pub &'static str); impl HashDomain for Domain { @@ -114,11 +124,21 @@ pub(crate) fn hash(domain: &D, msg: impl Iterator) - extract_p(&hash_to_point(domain, msg)) } +/// Trait representing a domain in which [`sinsemilla::commit`] and +/// [`sinsemilla::short_commit`] can be used. +/// +/// [`sinsemilla::commit`]: self::commit +/// [`sinsemilla::short_commit`]: self::short_commit pub trait CommitDomain: HashDomain { #[allow(non_snake_case)] fn R(&self) -> pallas::Point; } +/// A domain with a specific prefix string, in which [`sinsemilla::commit`] and +/// [`sinsemilla::short_commit`] can be used. +/// +/// [`sinsemilla::commit`]: self::commit +/// [`sinsemilla::short_commit`]: self::short_commit pub struct Comm(pub &'static str); impl HashDomain for Comm { From 873e1b7d7e03617acb9508f208347be95198f351 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 19 Mar 2021 08:43:18 +0800 Subject: [PATCH 4/8] Call hash_to_curve() only when constructing new domain Co-authored-by: Daira Hopwood Co-authored-by: Jack Grigg --- src/primitives/sinsemilla.rs | 167 +++++++++++++++++------------------ src/spec.rs | 4 +- 2 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 2a18f2f8..a8ac320d 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -76,107 +76,106 @@ impl> Iterator for Pad { } } -/// Trait representing a domain in which [`sinsemilla::hash_to_point`] and +/// A domain in which [`sinsemilla::hash_to_point`] and /// [`sinsemilla::hash`] can be used. /// /// [`sinsemilla::hash_to_point`]: self::hash_to_point /// [`sinsemilla::hash`]: self::hash -pub trait HashDomain { - #[allow(non_snake_case)] - fn Q(&self) -> pallas::Point; +#[allow(non_snake_case)] +pub struct HashDomain { + Q: pallas::Point, } -/// A domain with a specific prefix string, in which [`sinsemilla::hash_to_point`] and -/// [`sinsemilla::hash`] can be used. -/// -/// [`sinsemilla::hash_to_point`]: self::hash_to_point -/// [`sinsemilla::hash`]: self::hash -pub struct Domain(pub &'static str); +impl HashDomain { + /// Construct a new HashDomain with a specific prefix string + pub(crate) fn new(domain: &str) -> Self { + HashDomain { + Q: pallas::Point::hash_to_curve(Q_PERSONALIZATION)(domain.as_bytes()), + } + } -impl HashDomain for Domain { - fn Q(&self) -> pallas::Point { - pallas::Point::hash_to_curve(Q_PERSONALIZATION)(self.0.as_bytes()) + /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. + /// + /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash + #[allow(non_snake_case)] + pub(crate) fn hash_to_point(&self, msg: impl Iterator) -> pallas::Point { + let padded: Vec<_> = Pad::new(msg).collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + padded + .chunks(K) + .fold(self.Q, |acc, chunk| acc.double() + S(chunk)) + } + + /// `SinsemillaHash` from [§ 5.4.1.9][concretesinsemillahash]. + /// + /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash + pub(crate) fn hash(&self, msg: impl Iterator) -> pallas::Base { + extract_p(&self.hash_to_point(msg)) } } -/// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. -/// -/// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash -#[allow(non_snake_case)] -pub(crate) fn hash_to_point( - domain: &D, - msg: impl Iterator, -) -> pallas::Point { - let padded: Vec<_> = Pad::new(msg).collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - padded - .chunks(K) - .fold(domain.Q(), |acc, chunk| acc.double() + S(chunk)) -} - -/// `SinsemillaHash` from [§ 5.4.1.9][concretesinsemillahash]. -/// -/// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash -pub(crate) fn hash(domain: &D, msg: impl Iterator) -> pallas::Base { - extract_p(&hash_to_point(domain, msg)) -} - -/// Trait representing a domain in which [`sinsemilla::commit`] and +/// A domain in which [`sinsemilla::commit`] and /// [`sinsemilla::short_commit`] can be used. /// /// [`sinsemilla::commit`]: self::commit /// [`sinsemilla::short_commit`]: self::short_commit -pub trait CommitDomain: HashDomain { - #[allow(non_snake_case)] - fn R(&self) -> pallas::Point; -} - -/// A domain with a specific prefix string, in which [`sinsemilla::commit`] and -/// [`sinsemilla::short_commit`] can be used. -/// -/// [`sinsemilla::commit`]: self::commit -/// [`sinsemilla::short_commit`]: self::short_commit -pub struct Comm(pub &'static str); - -impl HashDomain for Comm { - fn Q(&self) -> pallas::Point { - let m_prefix = self.0.to_owned() + "-M"; - pallas::Point::hash_to_curve(Q_PERSONALIZATION)(m_prefix.as_bytes()) - } -} - -impl CommitDomain for Comm { - fn R(&self) -> pallas::Point { - let r_prefix = self.0.to_owned() + "-r"; - let hasher_r = pallas::Point::hash_to_curve(&r_prefix); - hasher_r(&[]) - } -} - -/// `SinsemillaCommit` from [§ 5.4.8.4][concretesinsemillacommit]. -/// -/// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit #[allow(non_snake_case)] -pub(crate) fn commit( - domain: &D, - msg: impl Iterator, - r: &pallas::Scalar, -) -> pallas::Point { - hash_to_point(domain, msg) + domain.R() * r +pub struct CommitDomain { + Q: pallas::Point, + R: pallas::Point, } -/// `SinsemillaShortCommit` from [§ 5.4.8.4][concretesinsemillacommit]. -/// -/// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit -pub(crate) fn short_commit( - domain: &D, - msg: impl Iterator, - r: &pallas::Scalar, -) -> pallas::Base { - extract_p(&commit(domain, msg, r)) +impl CommitDomain { + /// Construct a new CommitDomain with a specific prefix string + pub(crate) fn new(domain: &str) -> Self { + let m_prefix = domain.to_owned() + "-M"; + let r_prefix = domain.to_owned() + "-r"; + CommitDomain { + Q: HashDomain::new(&m_prefix).Q, + R: pallas::Point::hash_to_curve(&r_prefix.clone())(&[]), + } + } + + /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. + /// + /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash + #[allow(non_snake_case)] + pub(crate) fn hash_to_point(&self, msg: impl Iterator) -> pallas::Point { + let padded: Vec<_> = Pad::new(msg).collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + padded + .chunks(K) + .fold(self.Q, |acc, chunk| acc.double() + S(chunk)) + } + + /// `SinsemillaCommit` from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + #[allow(non_snake_case)] + pub(crate) fn commit( + &self, + msg: impl Iterator, + r: &pallas::Scalar, + ) -> pallas::Point { + self.hash_to_point(msg) + self.R * r + } + + /// `SinsemillaShortCommit` from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + pub(crate) fn short_commit( + &self, + msg: impl Iterator, + r: &pallas::Scalar, + ) -> pallas::Base { + extract_p(&self.commit(msg, r)) + } } #[cfg(test)] diff --git a/src/spec.rs b/src/spec.rs index 969ef331..1c7e2203 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -40,8 +40,8 @@ pub(crate) fn commit_ivk( ) -> pallas::Scalar { // We rely on the API contract that to_le_bits() returns at least PrimeField::NUM_BITS // bits, which is equal to L_ORCHARD_BASE. - let ivk = sinsemilla::short_commit( - &sinsemilla::Comm("z.cash:Orchard-CommitIvk"), + let domain = sinsemilla::CommitDomain::new(&"z.cash:Orchard-CommitIvk"); + let ivk = domain.short_commit( iter::empty() .chain(ak.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)) .chain(nk.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)), From 18fba2a62e7b52e9f39d2be72267dd58cfc3d9b0 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 19 Mar 2021 09:15:53 +0800 Subject: [PATCH 5/8] Add getters for Q() and R() --- src/primitives/sinsemilla.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index a8ac320d..00876420 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -115,6 +115,12 @@ impl HashDomain { pub(crate) fn hash(&self, msg: impl Iterator) -> pallas::Base { extract_p(&self.hash_to_point(msg)) } + + /// Return `Q` + #[allow(non_snake_case)] + pub(crate) fn Q(&self) -> pallas::Point { + self.Q + } } /// A domain in which [`sinsemilla::commit`] and @@ -176,6 +182,18 @@ impl CommitDomain { ) -> pallas::Base { extract_p(&self.commit(msg, r)) } + + /// Return `Q` + #[allow(non_snake_case)] + pub(crate) fn Q(&self) -> pallas::Point { + self.Q + } + + /// Return `R` + #[allow(non_snake_case)] + pub(crate) fn R(&self) -> pallas::Point { + self.R + } } #[cfg(test)] From 7a210fabf386009dd08721f2a224ce3d6a46e2d4 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Sat, 20 Mar 2021 12:10:09 +0800 Subject: [PATCH 6/8] Store HashDomain in CommitDomain Co-authored-by: Jack Grigg --- src/primitives.rs | 2 +- src/primitives/sinsemilla.rs | 43 ++++++++---------------------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/src/primitives.rs b/src/primitives.rs index 2607b61a..3c663af7 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -5,4 +5,4 @@ // - EphemeralSecretKey pub mod redpallas; -pub(crate) mod sinsemilla; +pub mod sinsemilla; diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 00876420..915b23fe 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -76,11 +76,9 @@ impl> Iterator for Pad { } } -/// A domain in which [`sinsemilla::hash_to_point`] and -/// [`sinsemilla::hash`] can be used. -/// -/// [`sinsemilla::hash_to_point`]: self::hash_to_point -/// [`sinsemilla::hash`]: self::hash +/// A domain in which [`Self::hash_to_point()`] and +/// [`Self::hash()`] can be used. +#[derive(Debug)] #[allow(non_snake_case)] pub struct HashDomain { Q: pallas::Point, @@ -123,14 +121,12 @@ impl HashDomain { } } -/// A domain in which [`sinsemilla::commit`] and -/// [`sinsemilla::short_commit`] can be used. -/// -/// [`sinsemilla::commit`]: self::commit -/// [`sinsemilla::short_commit`]: self::short_commit +/// A domain in which [`Self::commit`] and +/// [`Self::short_commit`] can be used. +#[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { - Q: pallas::Point, + M: HashDomain, R: pallas::Point, } @@ -140,26 +136,11 @@ impl CommitDomain { let m_prefix = domain.to_owned() + "-M"; let r_prefix = domain.to_owned() + "-r"; CommitDomain { - Q: HashDomain::new(&m_prefix).Q, + M: HashDomain::new(&m_prefix), R: pallas::Point::hash_to_curve(&r_prefix.clone())(&[]), } } - /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. - /// - /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash - #[allow(non_snake_case)] - pub(crate) fn hash_to_point(&self, msg: impl Iterator) -> pallas::Point { - let padded: Vec<_> = Pad::new(msg).collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - padded - .chunks(K) - .fold(self.Q, |acc, chunk| acc.double() + S(chunk)) - } - /// `SinsemillaCommit` from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -169,7 +150,7 @@ impl CommitDomain { msg: impl Iterator, r: &pallas::Scalar, ) -> pallas::Point { - self.hash_to_point(msg) + self.R * r + self.M.hash_to_point(msg) + self.R * r } /// `SinsemillaShortCommit` from [§ 5.4.8.4][concretesinsemillacommit]. @@ -183,12 +164,6 @@ impl CommitDomain { extract_p(&self.commit(msg, r)) } - /// Return `Q` - #[allow(non_snake_case)] - pub(crate) fn Q(&self) -> pallas::Point { - self.Q - } - /// Return `R` #[allow(non_snake_case)] pub(crate) fn R(&self) -> pallas::Point { From 9c75839e62a15f51c3f2353df06c709610f81a31 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 24 Mar 2021 12:16:53 +0800 Subject: [PATCH 7/8] Minor changes Co-authored-by: Jack Grigg --- src/primitives.rs | 2 +- src/primitives/sinsemilla.rs | 26 ++++++++++++++------------ src/primitives/sinsemilla/constants.rs | 9 +++++---- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/primitives.rs b/src/primitives.rs index 3c663af7..2607b61a 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -5,4 +5,4 @@ // - EphemeralSecretKey pub mod redpallas; -pub mod sinsemilla; +pub(crate) mod sinsemilla; diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 915b23fe..59bb57d0 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -76,8 +76,8 @@ impl> Iterator for Pad { } } -/// A domain in which [`Self::hash_to_point()`] and -/// [`Self::hash()`] can be used. +/// A domain in which $\mathsf{SinsemillaHashToPoint}$ and $\mathsf{SinsemillaHash}$ can +/// be used. #[derive(Debug)] #[allow(non_snake_case)] pub struct HashDomain { @@ -85,14 +85,14 @@ pub struct HashDomain { } impl HashDomain { - /// Construct a new HashDomain with a specific prefix string + /// Constructs a new `HashDomain` with a specific prefix string. pub(crate) fn new(domain: &str) -> Self { HashDomain { Q: pallas::Point::hash_to_curve(Q_PERSONALIZATION)(domain.as_bytes()), } } - /// `SinsemillaHashToPoint` from [§ 5.4.1.9][concretesinsemillahash]. + /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash #[allow(non_snake_case)] @@ -107,22 +107,23 @@ impl HashDomain { .fold(self.Q, |acc, chunk| acc.double() + S(chunk)) } - /// `SinsemillaHash` from [§ 5.4.1.9][concretesinsemillahash]. + /// $\mathsf{SinsemillaHash}$ from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash pub(crate) fn hash(&self, msg: impl Iterator) -> pallas::Base { extract_p(&self.hash_to_point(msg)) } - /// Return `Q` + /// Returns the Sinsemilla $Q$ constant for this domain. + #[cfg(test)] #[allow(non_snake_case)] pub(crate) fn Q(&self) -> pallas::Point { self.Q } } -/// A domain in which [`Self::commit`] and -/// [`Self::short_commit`] can be used. +/// A domain in which $\mathsf{SinsemillaCommit}$ and $\mathsf{SinsemillaShortCommit}$ can +/// be used. #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { @@ -131,7 +132,7 @@ pub struct CommitDomain { } impl CommitDomain { - /// Construct a new CommitDomain with a specific prefix string + /// Constructs a new `CommitDomain` with a specific prefix string. pub(crate) fn new(domain: &str) -> Self { let m_prefix = domain.to_owned() + "-M"; let r_prefix = domain.to_owned() + "-r"; @@ -141,7 +142,7 @@ impl CommitDomain { } } - /// `SinsemillaCommit` from [§ 5.4.8.4][concretesinsemillacommit]. + /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit #[allow(non_snake_case)] @@ -153,7 +154,7 @@ impl CommitDomain { self.M.hash_to_point(msg) + self.R * r } - /// `SinsemillaShortCommit` from [§ 5.4.8.4][concretesinsemillacommit]. + /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit pub(crate) fn short_commit( @@ -164,7 +165,8 @@ impl CommitDomain { extract_p(&self.commit(msg, r)) } - /// Return `R` + /// Returns the Sinsemilla $R$ constant for this domain. + #[cfg(test)] #[allow(non_snake_case)] pub(crate) fn R(&self) -> pallas::Point { self.R diff --git a/src/primitives/sinsemilla/constants.rs b/src/primitives/sinsemilla/constants.rs index beaa8c13..cb350bac 100644 --- a/src/primitives/sinsemilla/constants.rs +++ b/src/primitives/sinsemilla/constants.rs @@ -1,17 +1,18 @@ //! Sinsemilla generators -/// Number of bits of each message piece in SinsemillaHashToPoint +/// Number of bits of each message piece in $\mathsf{SinsemillaHashToPoint}$ pub const K: usize = 10; -/// The largest integer such that 2^c <= (r_P - 1) / 2, where r_P is the order +/// The largest integer such that $2^c \leq (r_P - 1) / 2$, where $r_P$ is the order /// of Pallas. pub const C: usize = 253; // Sinsemilla Q generators -/// SWU hash-to-curve personalization for Sinsemilla Q generators + +/// SWU hash-to-curve personalization for Sinsemilla $Q$ generators. pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ"; // Sinsemilla S generators -/// SWU hash-to-curve personalization for Sinsemilla S generators +/// SWU hash-to-curve personalization for Sinsemilla $S$ generators. pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS"; From a2c1bfb52a8e317f7a3a0cc6def16189aa79ab06 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 24 Mar 2021 12:30:03 +0800 Subject: [PATCH 8/8] Remove unnecessary clone() Co-authored-by: Jack Grigg --- src/primitives/sinsemilla.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/primitives/sinsemilla.rs b/src/primitives/sinsemilla.rs index 59bb57d0..bf9e5783 100644 --- a/src/primitives/sinsemilla.rs +++ b/src/primitives/sinsemilla.rs @@ -134,11 +134,12 @@ pub struct CommitDomain { impl CommitDomain { /// Constructs a new `CommitDomain` with a specific prefix string. pub(crate) fn new(domain: &str) -> Self { - let m_prefix = domain.to_owned() + "-M"; - let r_prefix = domain.to_owned() + "-r"; + let m_prefix = format!("{}-M", domain); + let r_prefix = format!("{}-r", domain); + let hasher_r = pallas::Point::hash_to_curve(&r_prefix); CommitDomain { M: HashDomain::new(&m_prefix), - R: pallas::Point::hash_to_curve(&r_prefix.clone())(&[]), + R: hasher_r(&[]), } }