From 499dc1e0524e1fba10d6f73eabdd6b04ee189c55 Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Thu, 7 Jan 2021 17:23:39 +0100 Subject: [PATCH 1/2] Blinding factor as parameter of Note::obfuscated The blinding factor is required to prove the knowledge of the value commitment of the note. If the blinding factor is not provided by the note creator, the latter will not be able to fetch this information, and consequentially won't be able to create a zk proof of knownledge of the value commitment without the view key of the owner of the note. This is not desirable since a note should be created only with the public key of the receiver. --- CHANGELOG.md | 7 +++++- Cargo.toml | 2 +- src/note.rs | 53 +++++++++++++++++++++++++--------------------- tests/note_test.rs | 12 +++++++---- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbf495..ff379dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.6.0] - 07-01-21 +### Changed +- Blinding factor provided to create obfuscated notes +- Transparent note with constant blinding factor + ## [0.5.1] - 06-01-21 -### Fix +### Fixed - #41 - Wrong value commitment for transparent notes ## [0.5.0] - 27-11-20 diff --git a/Cargo.toml b/Cargo.toml index 6a725df..92fa582 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-core" -version = "0.5.1" +version = "0.6.0" authors = ["zer0 ", "Victor Lopez Self { let r = JubJubScalar::random(rng); let nonce = JubJubScalar::random(rng); - // Blinding factor and value commitment are open for transparent note - // In order to save storage, these may not be stored and should be - // hardcoded for an eventual proof of knowledge of the - // commitment - let blinding_factor = match note_type { - NoteType::Transparent => JubJubScalar::zero(), - NoteType::Obfuscated => JubJubScalar::random(rng), - }; - Self::deterministic(note_type, &r, nonce, psk, value, blinding_factor) } /// Creates a new transparent note + /// + /// The blinding factor will be constant zero since the value commitment + /// exists only to shield the value. The value is not hidden for transparent + /// notes, so this can be trivially treated as a constant. pub fn transparent( rng: &mut R, psk: &PublicSpendKey, value: u64, ) -> Self { - Self::new(rng, NoteType::Transparent, psk, value) + Self::new(rng, NoteType::Transparent, psk, value, TRANSPARENT_BLINDER) } /// Creates a new obfuscated note + /// + /// The provided blinding factor will be used to calculate the value + /// commitment of the note. The tuple (value, blinding_factor), known by + /// the caller of this function, must be later used to prove the + /// knowledge of the value commitment of this note. pub fn obfuscated( rng: &mut R, psk: &PublicSpendKey, value: u64, + blinding_factor: JubJubScalar, ) -> Self { - Self::new(rng, NoteType::Obfuscated, psk, value) + Self::new(rng, NoteType::Obfuscated, psk, value, blinding_factor) } /// Create a new phoenix output note without inner randomness @@ -134,9 +139,11 @@ impl Note { let encrypted_data = match note_type { NoteType::Transparent => { - let mut encrypted_data = - [BlsScalar::zero(); PoseidonCipher::cipher_size()]; + let zero = TRANSPARENT_BLINDER.into(); + let mut encrypted_data = [zero; PoseidonCipher::cipher_size()]; + encrypted_data[0] = BlsScalar::from(value); + PoseidonCipher::new(encrypted_data) } NoteType::Obfuscated => { @@ -259,15 +266,14 @@ impl Note { /// succeeds for transparent notes, might fails or return random values for /// obfuscated notes if the provided view key is wrong. pub fn value(&self, vk: Option<&ViewKey>) -> Result { - match self.note_type { - NoteType::Transparent => { + match (self.note_type, vk) { + (NoteType::Transparent, _) => { let value = self.encrypted_data.cipher(); let value = value[0].reduce(); Ok(value.0[0]) } - NoteType::Obfuscated if vk.is_some() => { - let (value, _) = self.decrypt_data(vk.unwrap())?; - Ok(value) + (NoteType::Obfuscated, Some(vk)) => { + self.decrypt_data(vk).map(|(value, _)| value) } _ => Err(Error::MissingViewKey), } @@ -280,12 +286,11 @@ impl Note { &self, vk: Option<&ViewKey>, ) -> Result { - match self.note_type { - NoteType::Transparent => Ok(JubJubScalar::zero()), - NoteType::Obfuscated if vk.is_some() => { - let (_, blinding_factor) = self.decrypt_data(vk.unwrap())?; - Ok(blinding_factor) - } + match (self.note_type, vk) { + (NoteType::Transparent, _) => Ok(TRANSPARENT_BLINDER), + (NoteType::Obfuscated, Some(vk)) => self + .decrypt_data(vk) + .map(|(_, blinding_factor)| blinding_factor), _ => Err(Error::MissingViewKey), } } diff --git a/tests/note_test.rs b/tests/note_test.rs index a52082a..a8fd37f 100644 --- a/tests/note_test.rs +++ b/tests/note_test.rs @@ -36,7 +36,8 @@ fn obfuscated_note() -> Result<(), Error> { let vk = ssk.view_key(); let value = 25; - let note = Note::obfuscated(rng, &psk, value); + let blinding_factor = JubJubScalar::random(rng); + let note = Note::obfuscated(rng, &psk, value, blinding_factor); assert_eq!(note.note(), NoteType::Obfuscated); assert_eq!(value, note.value(Some(&vk))?); @@ -108,7 +109,8 @@ fn value_commitment_obfuscated() { let psk = ssk.public_key(); let value = 25; - let note = Note::obfuscated(rng, &psk, value); + let blinding_factor = JubJubScalar::random(rng); + let note = Note::obfuscated(rng, &psk, value, blinding_factor); let value = note .value(Some(&vsk)) @@ -141,7 +143,8 @@ fn note_keys_consistency() { assert_ne!(ssk, wrong_ssk); assert_ne!(vk, wrong_vk); - let note = Note::obfuscated(rng, &psk, value); + let blinding_factor = JubJubScalar::random(rng); + let note = Note::obfuscated(rng, &psk, value, blinding_factor); assert!(!wrong_vk.owns(¬e)); assert!(vk.owns(¬e)); @@ -156,7 +159,8 @@ fn fee_and_crossover_generation() -> Result<(), Error> { let vk = ssk.view_key(); let value = 25; - let note = Note::obfuscated(rng, &psk, value); + let blinding_factor = JubJubScalar::random(rng); + let note = Note::obfuscated(rng, &psk, value, blinding_factor); let (fee, crossover): (Fee, Crossover) = note.try_into()?; let ssk_fee = SecretSpendKey::random(rng); From 8064582cd2c253f43b2e8f86d10b2d67e4f6a27c Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Thu, 7 Jan 2021 19:52:35 +0100 Subject: [PATCH 2/2] Changelog fix for v0.6.0 --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff379dd..64faaf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.6.0] - 07-01-21 ### Changed - Blinding factor provided to create obfuscated notes -- Transparent note with constant blinding factor ## [0.5.1] - 06-01-21 ### Fixed