From df4bf422f5c1b4fc8b1364af7a4d0594dc25daa5 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Sat, 5 Jun 2021 15:49:55 +0800 Subject: [PATCH 1/4] gadget::sinsemilla.rs: Add CommitDomain SinsemillaInstructions gains several associated types specific to SinsemillaCommit. --- src/circuit/gadget/sinsemilla.rs | 93 ++++++++++++++++++++ src/circuit/gadget/sinsemilla/chip.rs | 29 +++++- src/circuit/gadget/sinsemilla/merkle/chip.rs | 10 +++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 79ccab30..84680040 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -36,9 +36,13 @@ pub trait SinsemillaInstructions; + /// CommitDomains used in this instruction. + type CommitDomains: CommitDomains; /// Witness a message piece given a field element. Returns a [`Self::MessagePiece`] /// encoding the given message. @@ -222,6 +226,7 @@ pub struct HashDomain< EccChip: EccInstructions< C, Point = >::Point, + FixedPoints = >::FixedPoints, > + Clone + Debug + Eq, @@ -238,6 +243,7 @@ where EccChip: EccInstructions< C, Point = >::Point, + FixedPoints = >::FixedPoints, > + Clone + Debug + Eq, @@ -284,12 +290,99 @@ where } } +/// Trait allowing circuit's Sinsemilla CommitDomains to be enumerated. +pub trait CommitDomains>: + Clone + Debug +{ + /// Returns the fixed point corresponding to the R constant for this CommitDomain. + fn r(&self) -> F; + + /// Returns the HashDomain contained in this CommitDomain + fn hash_domain(&self) -> H; +} + /// Trait allowing circuit's Sinsemilla HashDomains to be enumerated. #[allow(non_snake_case)] pub trait HashDomains: Clone + Debug { fn Q(&self) -> C; } +#[allow(non_snake_case)] +pub struct CommitDomain< + C: CurveAffine, + SinsemillaChip, + EccChip, + const K: usize, + const MAX_WORDS: usize, +> where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + Point = >::Point, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + M: HashDomain, + R: ecc::FixedPoint, +} + +impl + CommitDomain +where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + Point = >::Point, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + /// Constructs a new `CommitDomain` for the given domain. + pub fn new( + sinsemilla_chip: SinsemillaChip, + ecc_chip: EccChip, + domain: &SinsemillaChip::CommitDomains, + ) -> Self { + CommitDomain { + M: HashDomain::new(sinsemilla_chip, ecc_chip.clone(), &domain.hash_domain()), + R: ecc::FixedPoint::from_inner(ecc_chip, domain.r()), + } + } + + /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + pub fn commit( + &self, + mut layouter: impl Layouter, + message: Message, + r: Option, + ) -> Result, Error> { + assert_eq!(self.M.sinsemilla_chip, message.chip); + let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; + self.M + .hash_to_point(layouter.namespace(|| "M"), message)? + .add_incomplete(layouter.namespace(|| "M ⸭ [r] R"), &blind) + } + + /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + pub fn short_commit( + &self, + mut layouter: impl Layouter, + message: Message, + r: Option, + ) -> Result, Error> { + assert_eq!(self.M.sinsemilla_chip, message.chip); + let p = self.commit(layouter.namespace(|| "commit"), message, r); + p.map(|p| p.extract_p()) + } +} + #[cfg(test)] mod tests { use halo2::{ diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index b1452baf..598e9977 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -1,12 +1,13 @@ use super::{ message::{Message, MessagePiece}, - HashDomains, SinsemillaInstructions, + CommitDomains, HashDomains, SinsemillaInstructions, }; use crate::{ circuit::gadget::{ ecc::chip::EccPoint, utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue, Var}, }, + constants::OrchardFixedBasesFull, primitives::sinsemilla::{ self, Q_COMMIT_IVK_M_GENERATOR, Q_MERKLE_CRH, Q_NOTE_COMMITMENT_M_GENERATOR, }, @@ -267,8 +268,10 @@ impl SinsemillaInstructions; type Point = EccPoint; + type FixedPoints = OrchardFixedBasesFull; type HashDomains = SinsemillaHashDomains; + type CommitDomains = SinsemillaCommitDomains; fn witness_message_piece( &self, @@ -340,3 +343,27 @@ impl HashDomains for SinsemillaHashDomains { } } } + +#[derive(Clone, Debug)] +pub enum SinsemillaCommitDomains { + NoteCommit, + CommitIvk, +} + +impl CommitDomains + for SinsemillaCommitDomains +{ + fn r(&self) -> OrchardFixedBasesFull { + match self { + Self::NoteCommit => OrchardFixedBasesFull::NoteCommitR, + Self::CommitIvk => OrchardFixedBasesFull::CommitIvkR, + } + } + + fn hash_domain(&self) -> SinsemillaHashDomains { + match self { + Self::NoteCommit => SinsemillaHashDomains::NoteCommit, + Self::CommitIvk => SinsemillaHashDomains::CommitIvk, + } + } +} diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index e86d85a8..cede595b 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -466,12 +466,22 @@ impl SinsemillaInstructions>::Point; + type FixedPoints = >::FixedPoints; type HashDomains = >::HashDomains; + type CommitDomains = >::CommitDomains; fn witness_message_piece( &self, From 8ce0725043c8f9276eb8cb3d0a33c9696a351b2c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Sat, 5 Jun 2021 16:28:52 +0800 Subject: [PATCH 2/4] gadget::sinsemilla.rs: Add SinsemillaCommit test. --- src/circuit/gadget/sinsemilla.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 84680040..72b0aa27 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -388,14 +388,12 @@ mod tests { use halo2::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, - pasta::pallas, plonk::{Circuit, ConstraintSystem, Error}, }; use super::{ - chip::SinsemillaHashDomains, - chip::{SinsemillaChip, SinsemillaConfig}, - HashDomain, Message, MessagePiece, + chip::{SinsemillaChip, SinsemillaCommitDomains, SinsemillaConfig, SinsemillaHashDomains}, + CommitDomain, HashDomain, Message, MessagePiece, }; use crate::{ @@ -408,6 +406,7 @@ mod tests { }; use group::Curve; + use pasta_curves::{arithmetic::FieldExt, pallas}; use std::convert::TryInto; @@ -559,7 +558,7 @@ mod tests { }; Point::new( - ecc_chip, + ecc_chip.clone(), layouter.namespace(|| "Witness expected parent"), expected_parent, )? @@ -577,6 +576,22 @@ mod tests { )?; } + { + let chip2 = SinsemillaChip::construct(config.2); + + let commit_ivk = + CommitDomain::new(chip2.clone(), ecc_chip, &SinsemillaCommitDomains::CommitIvk); + let r = Some(pallas::Scalar::rand()); + let message: Vec> = + (0..500).map(|_| Some(rand::random::())).collect(); + let message = Message::from_bitstring( + chip2, + layouter.namespace(|| "witness message"), + message, + )?; + commit_ivk.commit(layouter.namespace(|| "commit"), message, r)?; + } + Ok(()) } } From a17a9301d7b58c27c4fc8ce663c1745b3d1c4000 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 9 Jul 2021 13:33:57 +0800 Subject: [PATCH 3/4] sinsemilla::tests: Witness and constrain expected result of commit. --- src/circuit/gadget/sinsemilla.rs | 51 ++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 72b0aa27..c6f794b9 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -401,7 +401,7 @@ mod tests { chip::{EccChip, EccConfig}, Point, }, - constants::MERKLE_CRH_PERSONALIZATION, + constants::{COMMIT_IVK_PERSONALIZATION, MERKLE_CRH_PERSONALIZATION}, primitives::sinsemilla::{self, K}, }; @@ -579,20 +579,47 @@ mod tests { { let chip2 = SinsemillaChip::construct(config.2); - let commit_ivk = - CommitDomain::new(chip2.clone(), ecc_chip, &SinsemillaCommitDomains::CommitIvk); - let r = Some(pallas::Scalar::rand()); + let commit_ivk = CommitDomain::new( + chip2.clone(), + ecc_chip.clone(), + &SinsemillaCommitDomains::CommitIvk, + ); + let r_val = pallas::Scalar::rand(); let message: Vec> = (0..500).map(|_| Some(rand::random::())).collect(); - let message = Message::from_bitstring( - chip2, - layouter.namespace(|| "witness message"), - message, - )?; - commit_ivk.commit(layouter.namespace(|| "commit"), message, r)?; - } - Ok(()) + let result = { + let message = Message::from_bitstring( + chip2, + layouter.namespace(|| "witness message"), + message.clone(), + )?; + commit_ivk.commit(layouter.namespace(|| "commit"), message, Some(r_val))? + }; + + // Witness expected result. + let expected_result = { + let message: Option> = message.into_iter().collect(); + let expected_result = if let Some(message) = message { + let domain = sinsemilla::CommitDomain::new(COMMIT_IVK_PERSONALIZATION); + let point = domain.commit(message.into_iter(), &r_val).unwrap(); + Some(point.to_affine()) + } else { + None + }; + + Point::new( + ecc_chip, + layouter.namespace(|| "Witness expected result"), + expected_result, + )? + }; + + result.constrain_equal( + layouter.namespace(|| "result == expected result"), + &expected_result, + ) + } } } From f44c4161af35c0c27b3ea81a00cd6e72ad467603 Mon Sep 17 00:00:00 2001 From: str4d Date: Mon, 19 Jul 2021 13:26:03 +0100 Subject: [PATCH 4/4] Adjust documentation of `CommitDomains::r` Co-authored-by: Daira Hopwood --- src/circuit/gadget/sinsemilla.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index c6f794b9..0b7c28f4 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -294,7 +294,8 @@ where pub trait CommitDomains>: Clone + Debug { - /// Returns the fixed point corresponding to the R constant for this CommitDomain. + /// Returns the fixed point corresponding to the R constant used for + /// randomization in this CommitDomain. fn r(&self) -> F; /// Returns the HashDomain contained in this CommitDomain