Browse Source

add spend field for tx builder and coin lookup trait

narodnik 5 years ago
parent
commit
bf88b9b946
5 changed files with 159 additions and 11 deletions
  1. 1 1
      src/bin/spend-classic.rs
  2. 18 3
      src/bin/tx.rs
  3. 21 0
      src/crypto/schnorr.rs
  4. 28 2
      src/crypto/spend_proof.rs
  5. 91 5
      src/tx.rs

+ 1 - 1
src/bin/spend-classic.rs

@@ -180,7 +180,7 @@ fn main() {
     let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
     let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
 
-    let merkle_path = [
+    let merkle_path = vec![
         (bls12_381::Scalar::random(&mut OsRng), true),
         (bls12_381::Scalar::random(&mut OsRng), false),
         (bls12_381::Scalar::random(&mut OsRng), true),

+ 18 - 3
src/bin/tx.rs

@@ -33,12 +33,15 @@ fn txbuilding() {
 
     let builder = tx::TransactionBuilder {
         clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110 }],
+        inputs: vec![],
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
     };
 
+    let mut coin_look = tx::CoinHashMap::new();
+
     let mut tx_data = vec![];
     {
-        let tx = builder.build(&mint_params, &spend_params);
+        let tx = builder.build(&mut coin_look, &mint_params, &spend_params);
         tx.encode(&mut tx_data).expect("encode tx");
     }
     let mut tree = CommitmentTree::empty();
@@ -65,12 +68,24 @@ fn txbuilding() {
     }
 
     let merkle_path = witness.path().unwrap();
-    let auth_path: Vec<Option<(bls12_381::Scalar, bool)>> = merkle_path
+    let auth_path: Vec<(bls12_381::Scalar, bool)> = merkle_path
         .auth_path
         .iter()
-        .map(|(node, b)| Some(((*node).into(), *b)))
+        .map(|(node, b)| ((*node).into(), *b))
         .collect();
 
+    // Make a spend tx
+
+    let coin = {
+        let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
+        tx.outputs[0].revealed.coin
+    };
+    let builder = tx::TransactionBuilder {
+        clear_inputs: vec![],
+        inputs: vec![tx::TransactionBuilderInputInfo { coin, merkle_path: auth_path }],
+        outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }]
+    };
+
     /*let note = Note {
         serial: jubjub::Fr::random(&mut OsRng),
         value: 110,

+ 21 - 0
src/crypto/schnorr.rs

@@ -1,7 +1,10 @@
 use ff::Field;
 use group::{Group, GroupEncoding};
 use rand::rngs::OsRng;
+use std::io;
 
+use crate::error::{Error, Result};
+use crate::serial::{Decodable, Encodable};
 use super::util::hash_to_scalar;
 
 pub struct SecretKey(pub jubjub::Fr);
@@ -35,6 +38,24 @@ pub struct Signature {
     response: jubjub::Fr,
 }
 
+impl Encodable for Signature {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.commit.encode(&mut s)?;
+        len += self.response.encode(s)?;
+        Ok(len)
+    }
+}
+
+impl Decodable for Signature {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            commit: Decodable::decode(&mut d)?,
+            response: Decodable::decode(d)?,
+        })
+    }
+}
+
 impl PublicKey {
     pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
         let challenge = hash_to_scalar(b"DarkFi_Schnorr", &signature.commit.to_bytes(), message);

+ 28 - 2
src/crypto/spend_proof.rs

@@ -7,10 +7,12 @@ use ff::{Field, PrimeField};
 use group::{Curve, GroupEncoding};
 use rand::rngs::OsRng;
 use std::time::Instant;
+use std::io;
 
 use super::coin::merkle_hash;
 use crate::circuit::spend_contract::SpendContract;
-use crate::error::Result;
+use crate::error::{Error, Result};
+use crate::serial::{Decodable, Encodable};
 
 pub struct SpendRevealedValues {
     pub value_commit: jubjub::SubgroupPoint,
@@ -147,6 +149,28 @@ impl SpendRevealedValues {
     }
 }
 
+impl Encodable for SpendRevealedValues {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.value_commit.encode(&mut s)?;
+        len += self.nullifier.encode(&mut s)?;
+        len += self.merkle_root.encode(&mut s)?;
+        len += self.signature_public.encode(s)?;
+        Ok(len)
+    }
+}
+
+impl Decodable for SpendRevealedValues {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            value_commit: Decodable::decode(&mut d)?,
+            nullifier: Decodable::decode(&mut d)?,
+            merkle_root: Decodable::decode(&mut d)?,
+            signature_public: Decodable::decode(d)?,
+        })
+    }
+}
+
 pub fn setup_spend_prover() -> groth16::Parameters<Bls12> {
     println!("Making random params...");
     let start = Instant::now();
@@ -182,9 +206,11 @@ pub fn create_spend_proof(
     serial: jubjub::Fr,
     randomness_coin: jubjub::Fr,
     secret: jubjub::Fr,
-    merkle_path: [(bls12_381::Scalar, bool); 4],
+    merkle_path: Vec<(bls12_381::Scalar, bool)>,
     signature_secret: jubjub::Fr,
 ) -> (groth16::Proof<Bls12>, SpendRevealedValues) {
+    assert_eq!(merkle_path.len(), 4);
+    assert_eq!(merkle_path.len(), super::coin::SAPLING_COMMITMENT_TREE_DEPTH);
     let c = SpendContract {
         value: Some(value),
         randomness_value: Some(randomness_value),

+ 91 - 5
src/tx.rs

@@ -1,3 +1,4 @@
+use std::collections::HashMap;
 use bellman::groth16;
 use bls12_381::Bls12;
 use ff::Field;
@@ -7,14 +8,51 @@ use std::io;
 
 use crate::crypto::{
     create_mint_proof, load_params, note::Note, save_params, setup_mint_prover, verify_mint_proof,
-    MintRevealedValues,
+    MintRevealedValues, SpendRevealedValues,
+    schnorr
 };
 use crate::error::{Error, Result};
 use crate::impl_vec;
 use crate::serial::{Decodable, Encodable, VarInt};
 
+pub trait CoinLookup {
+    fn lookup(&self, coin: &[u8; 32]) -> CoinAttributes;
+    fn add(&mut self, coin: [u8; 32], attrs: CoinAttributes);
+}
+
+#[derive(Clone)]
+pub struct CoinAttributes {
+    serial: jubjub::Fr,
+    coin_blind: jubjub::Fr,
+    valcom_blind: jubjub::Fr,
+    value: u64
+}
+
+pub struct CoinHashMap {
+    map: HashMap<[u8; 32], CoinAttributes>
+}
+
+impl CoinHashMap {
+    pub fn new() -> Self {
+        Self {
+            map: HashMap::new()
+        }
+    }
+}
+
+impl CoinLookup for CoinHashMap {
+    fn lookup(&self, coin: &[u8; 32]) -> CoinAttributes {
+        self.map[coin].clone()
+    }
+
+    fn add(&mut self, coin: [u8; 32], attrs: CoinAttributes) {
+        self.map.insert(coin, attrs);
+    }
+}
+
 pub struct TransactionBuilder {
     pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
+    pub inputs: Vec<TransactionBuilderInputInfo>,
     pub outputs: Vec<TransactionBuilderOutputInfo>,
 }
 
@@ -36,8 +74,9 @@ impl TransactionBuilder {
         lhs_total - rhs_total
     }
 
-    pub fn build(
+    pub fn build<C: CoinLookup>(
         self,
+        coin_look: &mut C,
         mint_params: &groth16::Parameters<Bls12>,
         spend_params: &groth16::Parameters<Bls12>,
     ) -> Transaction {
@@ -51,6 +90,11 @@ impl TransactionBuilder {
             clear_inputs.push(clear_input);
         }
 
+        let mut inputs = vec![];
+        for input in &self.inputs {
+            let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
+        }
+
         let mut outputs = vec![];
         let mut output_blinds = vec![];
         for (i, output) in self.outputs.iter().enumerate() {
@@ -64,6 +108,13 @@ impl TransactionBuilder {
             let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let coin_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
 
+            let coin_attrs = CoinAttributes {
+                serial: serial.clone(),
+                coin_blind: coin_blind.clone(),
+                valcom_blind: valcom_blind.clone(),
+                value: output.value
+            };
+
             let (mint_proof, revealed) = create_mint_proof(
                 mint_params,
                 output.value,
@@ -72,6 +123,9 @@ impl TransactionBuilder {
                 coin_blind,
                 output.public,
             );
+
+            coin_look.add(revealed.coin.clone(), coin_attrs);
+
             let output = TransactionOutput {
                 mint_proof,
                 revealed,
@@ -81,6 +135,7 @@ impl TransactionBuilder {
 
         Transaction {
             clear_inputs,
+            inputs,
             outputs,
         }
     }
@@ -91,8 +146,8 @@ pub struct TransactionBuilderClearInputInfo {
 }
 
 pub struct TransactionBuilderInputInfo {
-    pub value: u64,
-    pub serial: jubjub::Fr,
+    pub coin: [u8; 32],
+    pub merkle_path: Vec<(bls12_381::Scalar, bool)>,
 }
 
 pub struct TransactionBuilderOutputInfo {
@@ -102,6 +157,7 @@ pub struct TransactionBuilderOutputInfo {
 
 pub struct Transaction {
     pub clear_inputs: Vec<TransactionClearInput>,
+    pub inputs: Vec<TransactionInput>,
     pub outputs: Vec<TransactionOutput>,
 }
 
@@ -109,7 +165,8 @@ impl Encodable for Transaction {
     fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.clear_inputs.encode(&mut s)?;
-        len += self.outputs.encode(&mut s)?;
+        len += self.inputs.encode(&mut s)?;
+        len += self.outputs.encode(s)?;
         Ok(len)
     }
 }
@@ -118,6 +175,7 @@ impl Decodable for Transaction {
     fn decode<D: io::Read>(mut d: D) -> Result<Self> {
         Ok(Self {
             clear_inputs: Decodable::decode(&mut d)?,
+            inputs: Decodable::decode(&mut d)?,
             outputs: Decodable::decode(d)?,
         })
     }
@@ -172,6 +230,34 @@ impl Decodable for TransactionClearInput {
     }
 }
 
+pub struct TransactionInput {
+    pub spend_proof: groth16::Proof<Bls12>,
+    pub revealed: SpendRevealedValues,
+    pub signature: schnorr::Signature,
+}
+
+impl Encodable for TransactionInput {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.spend_proof.encode(&mut s)?;
+        len += self.revealed.encode(&mut s)?;
+        len += self.signature.encode(s)?;
+        Ok(len)
+    }
+}
+
+impl Decodable for TransactionInput {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            spend_proof: Decodable::decode(&mut d)?,
+            revealed: Decodable::decode(&mut d)?,
+            signature: Decodable::decode(d)?,
+        })
+    }
+}
+
+impl_vec!(TransactionInput);
+
 pub struct TransactionOutput {
     pub mint_proof: groth16::Proof<Bls12>,
     pub revealed: MintRevealedValues,