diff --git a/src/circuit.rs b/src/circuit.rs index 1730e008..6cf6fb9a 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -42,11 +42,13 @@ use gadget::{ StateWord, Word, }, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig, SinsemillaHashDomains}, + chip::{SinsemillaChip, SinsemillaCommitDomains, SinsemillaConfig, SinsemillaHashDomains}, + commit_ivk::CommitIvkConfig, merkle::{ chip::{MerkleChip, MerkleConfig}, MerklePath, }, + CommitDomain, }, utilities::{ copy, @@ -78,6 +80,7 @@ pub struct Config { merkle_config_2: MerkleConfig, sinsemilla_config_1: SinsemillaConfig, sinsemilla_config_2: SinsemillaConfig, + commit_ivk_config: CommitIvkConfig, } /// The Orchard Action circuit. @@ -233,6 +236,11 @@ impl plonk::Circuit for Circuit { (sinsemilla_config_2, merkle_config_2) }; + // Configuration to handle decomposition and canonicity checking + // for CommitIvk. + let commit_ivk_config = + CommitIvkConfig::configure(meta, advices, sinsemilla_config_1.clone()); + // TODO: Infrastructure to handle public inputs. let q_primary = meta.selector(); let primary = meta.instance_column(); @@ -263,6 +271,7 @@ impl plonk::Circuit for Circuit { merkle_config_2, sinsemilla_config_1, sinsemilla_config_2, + commit_ivk_config, } } @@ -543,6 +552,27 @@ impl plonk::Circuit for Circuit { alpha_commitment.add(layouter.namespace(|| "rk"), &ak)? }; + // Diversified address integrity. + let _pk_d_old = { + let commit_ivk_config = config.commit_ivk_config.clone(); + + let ivk = { + let rivk = self.rivk.map(|rivk| *rivk); + + commit_ivk_config.assign_region( + config.sinsemilla_chip_1(), + ecc_chip.clone(), + layouter.namespace(|| "CommitIvk"), + *ak.extract_p().inner(), + nk, + rivk, + )? + }; + + // [ivk] g_d_old + g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk.inner())? + }; + Ok(()) } } diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index dbcf8450..866e44dd 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -2,7 +2,7 @@ use pasta_curves::pallas; use ecc::chip::EccChip; use poseidon::Pow5T3Chip as PoseidonChip; -use sinsemilla::merkle::chip::MerkleChip; +use sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}; use utilities::plonk::PLONKChip; pub(crate) mod ecc; @@ -19,6 +19,14 @@ impl super::Config { EccChip::construct(self.ecc_config.clone()) } + pub(super) fn sinsemilla_chip_1(&self) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_1.clone()) + } + + pub(super) fn sinsemilla_chip_2(&self) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_2.clone()) + } + pub(super) fn merkle_chip_1(&self) -> MerkleChip { MerkleChip::construct(self.merkle_config_1.clone()) } diff --git a/src/constants.rs b/src/constants.rs index 50a26277..062ec384 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -43,6 +43,11 @@ pub(crate) const L_ORCHARD_SCALAR: usize = 255; /// $\ell_\mathsf{value}$ pub(crate) const L_VALUE: usize = 64; +/// T_PRIME_BITS is the smallest multiple of 10 such that 2^T_PRIME_BITS +/// is larger than t_P. t_P is defined in q_P = 2^254 + t_P for the +/// Pallas base field. +pub(crate) const PALLAS_T_PRIME_BITS: usize = 130; + /// SWU hash-to-curve personalization for the spending key base point and /// the nullifier base point K^Orchard pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard";