From caef323f9b9c70ba82e281c658e26faa8bb24855 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Fri, 24 Jul 2020 20:57:52 -0400 Subject: [PATCH] pedersen_hash_to_point() works, with submethods using bitvec Also tidy, document --- zebra-chain/src/notes.rs | 1 + zebra-chain/src/notes/sapling.rs | 7 +-- zebra-chain/src/notes/sapling/commitments.rs | 53 ++++++++------------ zebra-chain/src/notes/sprout.rs | 5 ++ zebra-chain/src/treestate.rs | 2 + zebra-chain/src/types/amount.rs | 1 + 6 files changed, 32 insertions(+), 37 deletions(-) diff --git a/zebra-chain/src/notes.rs b/zebra-chain/src/notes.rs index 5594ef8c..9ba29089 100644 --- a/zebra-chain/src/notes.rs +++ b/zebra-chain/src/notes.rs @@ -1,4 +1,5 @@ //! Note encryption types. + mod memo; pub mod sapling; diff --git a/zebra-chain/src/notes/sapling.rs b/zebra-chain/src/notes/sapling.rs index 0e7e2b1c..180dcb8b 100644 --- a/zebra-chain/src/notes/sapling.rs +++ b/zebra-chain/src/notes/sapling.rs @@ -1,3 +1,5 @@ +//! Sprout notes + #![allow(clippy::unit_arg)] #![allow(dead_code)] @@ -17,11 +19,6 @@ pub use ciphertexts::{EncryptedCiphertext, OutCiphertext}; pub use commitments::{CommitmentRandomness, NoteCommitment, ValueCommitment}; pub use nullifiers::Nullifier; -/// -/// -/// https://zips.z.cash/protocol/protocol.pdf#concretepedersenhash -pub fn pedersen_hash_to_point() {} - /// A Note represents that a value is spendable by the recipient who /// holds the spending key corresponding to a given shielded payment /// address. diff --git a/zebra-chain/src/notes/sapling/commitments.rs b/zebra-chain/src/notes/sapling/commitments.rs index 8f1b363a..e69f5bce 100644 --- a/zebra-chain/src/notes/sapling/commitments.rs +++ b/zebra-chain/src/notes/sapling/commitments.rs @@ -1,3 +1,5 @@ +//! Sapling note and value commitments + use std::{fmt, io}; use bitvec::prelude::*; @@ -14,30 +16,29 @@ use crate::{ // exported. type Scalar = jubjub::Fr; -pub fn pedersen_hash_to_point(domain: [u8; 8], M: BitVec) -> jubjub::ExtendedPoint { +#[allow(non_snake_case)] +pub fn pedersen_hash_to_point(domain: [u8; 8], M: &BitVec) -> jubjub::ExtendedPoint { // Expects i to be 0-indexed fn I_i(domain: [u8; 8], i: usize) -> jubjub::ExtendedPoint { find_group_hash(domain, &i.to_le_bytes()) } // ⟨Mᵢ⟩ - // fn m_i(segment: BitSlice) -> Scalar - // where - // O: BitOrder, - // T: BitStore, - // { - // let value = segment - // .chunks(3) - // .enumerate() - // .try_fold(0, |acc, (j, chunk)| { - // let mut bits = bits![Lsb0; 0; 3]; - // bits.copy_from_slice(chunk); + fn M_i(segment: &BitSlice) -> Scalar { + let mut m_i = [0u8; 32]; - // acc += (1 - 2 * bits[2] as u8) * (1 + bits[0] as u8 + 2 * bits[1] as u8) - // }); + for (j, chunk) in segment.chunks(3).enumerate() { + let mut data = [0u8; 3]; + let bits = data.bits_mut::(); + bits.copy_from_slice(chunk); - // Scalar::from_bytes(*value.into()).unwrap() - // } + let enc_m_j = (1 - (2 * bits[2] as u8)) * (1 + (bits[0] as u8) + (2 * bits[1] as u8)); + + m_i[0] += enc_m_j * (1 << (4 * j)) + } + + Scalar::from_bytes(&m_i).unwrap() + } let mut result = jubjub::ExtendedPoint::identity(); @@ -46,19 +47,7 @@ pub fn pedersen_hash_to_point(domain: [u8; 8], M: BitVec) -> jubjub::E // // https://zips.z.cash/protocol/protocol.pdf#concretepedersenhash for (i, segment) in M.chunks(189).enumerate() { - let mut m_i = [0u8; 32]; - - // ⟨Mᵢ⟩ - for (j, chunk) in segment.chunks(3).enumerate() { - let bits: &BitSlice<_, _> = [0u8; 3].bits::(); - bits.copy_from_slice(chunk); - - let enc_m_j = (1 - (2 * bits[2] as u8)) * (1 + (bits[0] as u8) + (2 * bits[1] as u8)); - - m_i[0] += enc_m_j * (1 << (4 * j)) - } - - result += I_i(domain, i) * Scalar::from_bytes(&m_i).unwrap() + result += I_i(domain, i) * M_i(&segment) } result @@ -74,7 +63,7 @@ pub fn pedersen_hash_to_point(domain: [u8; 8], M: BitVec) -> jubjub::E /// https://zips.z.cash/protocol/protocol.pdf#concretewindowedcommit pub fn windowed_pedersen_commitment_r( csprng: &mut T, - s: BitVec, + s: &BitVec, ) -> jubjub::ExtendedPoint where T: RngCore + CryptoRng, @@ -85,7 +74,7 @@ where csprng.fill_bytes(&mut r_bytes); let r = Scalar::from_bytes(&r_bytes).unwrap(); - pedersen_hash_to_point(D, s) + find_group_hash(D, b"r") * r + pedersen_hash_to_point(D, &s) + find_group_hash(D, b"r") * r } /// The randomness used in the Pedersen Hash for note commitment. @@ -174,7 +163,7 @@ impl NoteCommitment { s.append(&mut BitVec::::from_slice(&pk_d_bytes[..])); s.append(&mut BitVec::::from_slice(&v_bytes[..])); - Self::from(windowed_pedersen_commitment_r(csprng, s)) + Self::from(windowed_pedersen_commitment_r(csprng, &s)) } /// Hash Extractor for Jubjub (?) diff --git a/zebra-chain/src/notes/sprout.rs b/zebra-chain/src/notes/sprout.rs index bf45dfc4..1f346b6c 100644 --- a/zebra-chain/src/notes/sprout.rs +++ b/zebra-chain/src/notes/sprout.rs @@ -1,3 +1,5 @@ +//! Sprout notes + #![allow(clippy::unit_arg)] #![allow(dead_code)] @@ -39,6 +41,9 @@ pub struct Note { } impl Note { + /// NoteCommit_rcm^Sprout(a_pk, v, rho) + /// + /// https://zips.z.cash/protocol/protocol.pdf#concretesproutnotecommit pub fn commit(&self) -> NoteCommitment { let leading_byte: u8 = 0xB0; let mut hasher = Sha256::default(); diff --git a/zebra-chain/src/treestate.rs b/zebra-chain/src/treestate.rs index 32a6131a..925aaa36 100644 --- a/zebra-chain/src/treestate.rs +++ b/zebra-chain/src/treestate.rs @@ -1,2 +1,4 @@ +//! Treestate representations for Sprout and Sapling + pub mod note_commitment_tree; // mod nullifier_set; diff --git a/zebra-chain/src/types/amount.rs b/zebra-chain/src/types/amount.rs index 9831ddc7..7efe8740 100644 --- a/zebra-chain/src/types/amount.rs +++ b/zebra-chain/src/types/amount.rs @@ -22,6 +22,7 @@ impl Amount { self.0.try_into() } + /// To little endian byte array pub fn to_bytes(&self) -> [u8; 8] { self.0.to_le_bytes() }