working signatures for clear inputs (deposits)

This commit is contained in:
narodnik
2021-05-12 11:50:47 +02:00
parent c40b673120
commit 07eb99c465
2 changed files with 118 additions and 45 deletions

View File

@@ -4,6 +4,7 @@ use ff::{Field, PrimeField};
use group::Group;
use rand::rngs::OsRng;
use std::io;
use std::path::Path;
use sapvi::crypto::{
coin::Coin,
@@ -17,23 +18,33 @@ use sapvi::error::{Error, Result};
use sapvi::serial::{Decodable, Encodable, VarInt};
use sapvi::tx;
fn txbuilding() {
//{
// let params = setup_mint_prover();
// save_params("mint.params", &params);
//}
//{
// let params = setup_spend_prover();
// save_params("spend.params", &params);
//}
fn main() {
// Auto create trusted ceremony parameters if they don't exist
if !Path::new("mint.params").exists() {
let params = setup_mint_prover();
save_params("mint.params", &params);
}
if !Path::new("spend.params").exists() {
let params = setup_spend_prover();
save_params("spend.params", &params);
}
// Load trusted setup parameters
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");
// Cashier creates a secret key
let cashier_secret = jubjub::Fr::random(&mut OsRng);
// This is their public key
let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
// Wallet 1 creates a secret key
let secret = jubjub::Fr::random(&mut OsRng);
// This is their public key
let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
let builder = tx::TransactionBuilder {
clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110 }],
clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110, signature_secret: cashier_secret }],
inputs: vec![],
outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
};
@@ -106,22 +117,5 @@ fn txbuilding() {
let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
assert!(tx.verify(&mint_pvk, &spend_pvk));
}
/*let note = Note {
serial: jubjub::Fr::random(&mut OsRng),
value: 110,
coin_blind: jubjub::Fr::random(&mut OsRng),
valcom_blind: jubjub::Fr::random(&mut OsRng),
};
let secret = jubjub::Fr::random(&mut OsRng);
let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
let encrypted_note = note.encrypt(&public).unwrap();
let note2 = encrypted_note.decrypt(&secret).unwrap();
assert_eq!(note.value, note2.value);*/
}
fn main() {
txbuilding();
}

115
src/tx.rs
View File

@@ -26,7 +26,7 @@ pub struct TransactionBuilder {
impl TransactionBuilder {
fn compute_remainder_blind(
clear_inputs: &Vec<TransactionClearInput>,
clear_inputs: &Vec<PartialTransactionClearInput>,
input_blinds: &Vec<jubjub::Fr>,
output_blinds: &Vec<jubjub::Fr>,
) -> jubjub::Fr {
@@ -54,10 +54,14 @@ impl TransactionBuilder {
) -> Transaction {
let mut clear_inputs = vec![];
for input in &self.clear_inputs {
let signature_public =
zcash_primitives::constants::SPENDING_KEY_GENERATOR * input.signature_secret;
let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
let clear_input = TransactionClearInput {
let clear_input = PartialTransactionClearInput {
value: input.value,
valcom_blind,
signature_public
};
clear_inputs.push(clear_input);
}
@@ -69,8 +73,6 @@ impl TransactionBuilder {
input_blinds.push(input.note.valcom_blind.clone());
let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
let signature_public =
zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
// make proof
@@ -148,6 +150,14 @@ impl TransactionBuilder {
.encode(&mut unsigned_tx_data)
.expect("TODO handle this");
let mut clear_inputs = vec![];
for (input, info) in partial_tx.clear_inputs.into_iter().zip(self.clear_inputs) {
let secret = schnorr::SecretKey(info.signature_secret.clone());
let signature = secret.sign(&unsigned_tx_data[..]);
let input = TransactionClearInput::from_partial(input, signature);
clear_inputs.push(input);
}
let mut inputs = vec![];
for (input, signature_secret) in partial_tx
.inputs
@@ -160,7 +170,7 @@ impl TransactionBuilder {
}
Transaction {
clear_inputs: partial_tx.clear_inputs,
clear_inputs,
inputs,
outputs: partial_tx.outputs,
}
@@ -169,6 +179,7 @@ impl TransactionBuilder {
pub struct TransactionBuilderClearInputInfo {
pub value: u64,
pub signature_secret: jubjub::Fr,
}
pub struct TransactionBuilderInputInfo {
@@ -185,7 +196,7 @@ pub struct TransactionBuilderOutputInfo {
}
pub struct PartialTransaction {
pub clear_inputs: Vec<TransactionClearInput>,
pub clear_inputs: Vec<PartialTransactionClearInput>,
pub inputs: Vec<PartialTransactionInput>,
pub outputs: Vec<TransactionOutput>,
}
@@ -239,7 +250,7 @@ impl Decodable for Transaction {
impl Transaction {
fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += self.clear_inputs.encode(&mut s)?;
len += self.clear_inputs.encode_without_signature(&mut s)?;
len += self.inputs.encode_without_signature(&mut s)?;
len += self.outputs.encode(s)?;
Ok(len)
@@ -280,6 +291,12 @@ impl Transaction {
self
.encode_without_signature(&mut unsigned_tx_data)
.expect("TODO handle this");
for input in &self.clear_inputs {
let public = schnorr::PublicKey(input.signature_public.clone());
if !public.verify(&unsigned_tx_data[..], &input.signature) {
return false;
}
}
for input in &self.inputs {
let public = schnorr::PublicKey(input.revealed.signature_public.clone());
if !public.verify(&unsigned_tx_data[..], &input.signature) {
@@ -294,8 +311,47 @@ impl Transaction {
pub struct TransactionClearInput {
pub value: u64,
pub valcom_blind: jubjub::Fr,
pub signature_public: jubjub::SubgroupPoint,
pub signature: schnorr::Signature,
}
impl TransactionClearInput {
fn from_partial(partial: PartialTransactionClearInput, signature: schnorr::Signature) -> Self {
Self {
value: partial.value,
valcom_blind: partial.valcom_blind,
signature_public: partial.signature_public,
signature
}
}
fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += self.value.encode(&mut s)?;
len += self.valcom_blind.encode(&mut s)?;
len += self.signature_public.encode(s)?;
Ok(len)
}
}
macro_rules! impl_vec_without_signature {
($type: ty) => {
impl EncodableWithoutSignature for Vec<$type> {
#[inline]
fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += VarInt(self.len() as u64).encode(&mut s)?;
for c in self.iter() {
len += c.encode_without_signature(&mut s)?;
}
Ok(len)
}
}
};
}
impl_vec_without_signature!(TransactionClearInput);
impl_vec!(TransactionClearInput);
impl Encodable for TransactionClearInput {
@@ -303,6 +359,8 @@ impl Encodable for TransactionClearInput {
let mut len = 0;
len += self.value.encode(&mut s)?;
len += self.valcom_blind.encode(&mut s)?;
len += self.signature_public.encode(&mut s)?;
len += self.signature.encode(s)?;
Ok(len)
}
}
@@ -311,7 +369,37 @@ impl Decodable for TransactionClearInput {
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
Ok(Self {
value: Decodable::decode(&mut d)?,
valcom_blind: Decodable::decode(d)?,
valcom_blind: Decodable::decode(&mut d)?,
signature_public: Decodable::decode(&mut d)?,
signature: Decodable::decode(d)?,
})
}
}
pub struct PartialTransactionClearInput {
pub value: u64,
pub valcom_blind: jubjub::Fr,
pub signature_public: jubjub::SubgroupPoint,
}
impl_vec!(PartialTransactionClearInput);
impl Encodable for PartialTransactionClearInput {
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += self.value.encode(&mut s)?;
len += self.valcom_blind.encode(&mut s)?;
len += self.signature_public.encode(&mut s)?;
Ok(len)
}
}
impl Decodable for PartialTransactionClearInput {
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
Ok(Self {
value: Decodable::decode(&mut d)?,
valcom_blind: Decodable::decode(&mut d)?,
signature_public: Decodable::decode(&mut d)?,
})
}
}
@@ -368,16 +456,7 @@ trait EncodableWithoutSignature {
fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
}
impl EncodableWithoutSignature for Vec<TransactionInput> {
fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += VarInt(self.len() as u64).encode(&mut s)?;
for c in self.iter() {
len += c.encode_without_signature(&mut s)?;
}
Ok(len)
}
}
impl_vec_without_signature!(TransactionInput);
impl Encodable for TransactionInput {
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {