From 37baa83f16858ac254b6a4e8e256bfbe11eb7a13 Mon Sep 17 00:00:00 2001 From: narodnik Date: Tue, 11 May 2021 09:58:32 +0200 Subject: [PATCH] add encrypted output note --- src/bin/tx.rs | 33 +++++++++++++-------- src/bin/wallet/darkd.rs | 6 ++-- src/crypto/note.rs | 21 +++++++++++++ src/crypto/schnorr.rs | 2 +- src/crypto/spend_proof.rs | 7 +++-- src/tx.rs | 62 ++++++++++++++++++++++++++++++--------- 6 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/bin/tx.rs b/src/bin/tx.rs index a8c505241..3eadb821e 100644 --- a/src/bin/tx.rs +++ b/src/bin/tx.rs @@ -18,18 +18,19 @@ use sapvi::serial::{Decodable, Encodable, VarInt}; use sapvi::tx; fn txbuilding() { - { - let params = setup_mint_prover(); - save_params("mint.params", ¶ms); - } - { - let params = setup_spend_prover(); - save_params("spend.params", ¶ms); - } + //{ + // let params = setup_mint_prover(); + // save_params("mint.params", ¶ms); + //} + //{ + // let params = setup_spend_prover(); + // save_params("spend.params", ¶ms); + //} let (mint_params, mint_pvk) = load_params("mint.params").expect("params should load"); let (spend_params, spend_pvk) = load_params("spend.params").expect("params should load"); - let public = jubjub::SubgroupPoint::random(&mut OsRng); + let secret = jubjub::Fr::random(&mut OsRng); + let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret; let builder = tx::TransactionBuilder { clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110 }], @@ -49,12 +50,17 @@ fn txbuilding() { let cmu = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr()); tree.append(cmu); } + let note = { let tx = tx::Transaction::decode(&tx_data[..]).unwrap(); assert!(tx.verify(&mint_pvk)); tree.append(Coin::new(tx.outputs[0].revealed.coin)) .expect("append merkle"); - } + + // Try to decrypt output note + let note = tx.outputs[0].enc_note.decrypt(&secret).expect("note should be destined for us"); + note + }; let mut witness = IncrementalWitness::from_tree(&tree); assert_eq!(witness.position(), 5); assert_eq!(tree.root(), witness.root()); @@ -82,8 +88,11 @@ fn txbuilding() { }; let builder = tx::TransactionBuilder { clear_inputs: vec![], - inputs: vec![tx::TransactionBuilderInputInfo { coin, merkle_path: auth_path }], - outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }] + inputs: vec![tx::TransactionBuilderInputInfo { + coin, + merkle_path: auth_path, + }], + outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }], }; /*let note = Note { diff --git a/src/bin/wallet/darkd.rs b/src/bin/wallet/darkd.rs index eb96204b6..2f2013f08 100644 --- a/src/bin/wallet/darkd.rs +++ b/src/bin/wallet/darkd.rs @@ -4,16 +4,16 @@ use async_executor::Executor; use async_native_tls::TlsAcceptor; use async_std::sync::Mutex; use easy_parallel::Parallel; +use ff::Field; use http_types::{Request, Response, StatusCode}; use log::*; +use rand::rngs::OsRng; +use sapvi::serial; use serde_json::json; use smol::Async; use std::net::SocketAddr; use std::net::TcpListener; use std::sync::Arc; -use ff::Field; -use sapvi::serial; -use rand::rngs::OsRng; use sapvi::{net, Result}; diff --git a/src/crypto/note.rs b/src/crypto/note.rs index 8dcc3f5ec..22e74f58c 100644 --- a/src/crypto/note.rs +++ b/src/crypto/note.rs @@ -73,6 +73,27 @@ pub struct EncryptedNote { ephem_public: jubjub::SubgroupPoint, } +impl Encodable for EncryptedNote { + fn encode(&self, mut s: S) -> Result { + let mut len = 0; + s.write_slice(&self.ciphertext)?; + len += ENC_CIPHERTEXT_SIZE; + len += self.ephem_public.encode(&mut s)?; + Ok(len) + } +} + +impl Decodable for EncryptedNote { + fn decode(mut d: D) -> Result { + let mut ciphertext = [0u8; ENC_CIPHERTEXT_SIZE]; + d.read_slice(&mut ciphertext[..])?; + Ok(Self { + ciphertext, + ephem_public: Decodable::decode(d)? + }) + } +} + impl EncryptedNote { pub fn decrypt(&self, secret: &jubjub::Fr) -> Result { let shared_secret = sapling_ka_agree(&secret, &self.ephem_public.into()); diff --git a/src/crypto/schnorr.rs b/src/crypto/schnorr.rs index c578bcc06..06663492d 100644 --- a/src/crypto/schnorr.rs +++ b/src/crypto/schnorr.rs @@ -3,9 +3,9 @@ use group::{Group, GroupEncoding}; use rand::rngs::OsRng; use std::io; +use super::util::hash_to_scalar; use crate::error::{Error, Result}; use crate::serial::{Decodable, Encodable}; -use super::util::hash_to_scalar; pub struct SecretKey(pub jubjub::Fr); diff --git a/src/crypto/spend_proof.rs b/src/crypto/spend_proof.rs index bd5bf44eb..24e41c561 100644 --- a/src/crypto/spend_proof.rs +++ b/src/crypto/spend_proof.rs @@ -6,8 +6,8 @@ use bls12_381::Bls12; use ff::{Field, PrimeField}; use group::{Curve, GroupEncoding}; use rand::rngs::OsRng; -use std::time::Instant; use std::io; +use std::time::Instant; use super::coin::merkle_hash; use crate::circuit::spend_contract::SpendContract; @@ -210,7 +210,10 @@ pub fn create_spend_proof( signature_secret: jubjub::Fr, ) -> (groth16::Proof, SpendRevealedValues) { assert_eq!(merkle_path.len(), 4); - assert_eq!(merkle_path.len(), super::coin::SAPLING_COMMITMENT_TREE_DEPTH); + assert_eq!( + merkle_path.len(), + super::coin::SAPLING_COMMITMENT_TREE_DEPTH + ); let c = SpendContract { value: Some(value), randomness_value: Some(randomness_value), diff --git a/src/tx.rs b/src/tx.rs index d7c88d763..d330bacf6 100644 --- a/src/tx.rs +++ b/src/tx.rs @@ -1,15 +1,15 @@ -use std::collections::HashMap; use bellman::groth16; use bls12_381::Bls12; use ff::Field; use group::Group; use rand::rngs::OsRng; +use std::collections::HashMap; use std::io; use crate::crypto::{ - create_mint_proof, load_params, note::Note, save_params, setup_mint_prover, verify_mint_proof, + create_mint_proof, create_spend_proof, load_params, note::{Note, EncryptedNote}, save_params, schnorr, + setup_mint_prover, setup_spend_prover, verify_mint_proof, verify_spend_proof, MintRevealedValues, SpendRevealedValues, - schnorr }; use crate::error::{Error, Result}; use crate::impl_vec; @@ -24,18 +24,17 @@ pub trait CoinLookup { pub struct CoinAttributes { serial: jubjub::Fr, coin_blind: jubjub::Fr, - valcom_blind: jubjub::Fr, - value: u64 + value: u64, } pub struct CoinHashMap { - map: HashMap<[u8; 32], CoinAttributes> + map: HashMap<[u8; 32], CoinAttributes>, } impl CoinHashMap { pub fn new() -> Self { Self { - map: HashMap::new() + map: HashMap::new(), } } } @@ -93,6 +92,27 @@ impl TransactionBuilder { let mut inputs = vec![]; for input in &self.inputs { let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng); + + let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng); + let signature_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret; + + // make proof + let attrs = coin_look.lookup(&input.coin); + + /* + let (proof, revealed) = create_spend_proof( + &spend_params, + attrs.value, + valcom_blind.clone(), + attrs.serial, + attrs.coin_blind, + secret, + merkle_path, + signature_secret, + ); + */ + + // make signature } let mut outputs = vec![]; @@ -111,24 +131,35 @@ impl TransactionBuilder { let coin_attrs = CoinAttributes { serial: serial.clone(), coin_blind: coin_blind.clone(), - valcom_blind: valcom_blind.clone(), - value: output.value + value: output.value, }; let (mint_proof, revealed) = create_mint_proof( mint_params, output.value, - valcom_blind, - serial, - coin_blind, - output.public, + valcom_blind.clone(), + serial.clone(), + coin_blind.clone(), + output.public.clone(), ); coin_look.add(revealed.coin.clone(), coin_attrs); + // Encrypted note + + let note = Note { + serial, + value: output.value, + coin_blind, + valcom_blind, + }; + + let encrypted_note = note.encrypt(&output.public).unwrap(); + let output = TransactionOutput { mint_proof, revealed, + enc_note: encrypted_note }; outputs.push(output); } @@ -261,6 +292,7 @@ impl_vec!(TransactionInput); pub struct TransactionOutput { pub mint_proof: groth16::Proof, pub revealed: MintRevealedValues, + pub enc_note: EncryptedNote, } impl_vec!(TransactionOutput); @@ -270,6 +302,7 @@ impl Encodable for TransactionOutput { let mut len = 0; len += self.mint_proof.encode(&mut s)?; len += self.revealed.encode(&mut s)?; + len += self.enc_note.encode(&mut s)?; Ok(len) } } @@ -278,7 +311,8 @@ impl Decodable for TransactionOutput { fn decode(mut d: D) -> Result { Ok(Self { mint_proof: Decodable::decode(&mut d)?, - revealed: Decodable::decode(d)?, + revealed: Decodable::decode(&mut d)?, + enc_note: Decodable::decode(&mut d)?, }) } }