Просмотр исходного кода

verify summing coin blinds and checking token commits

narodnik 4 лет назад
Родитель
Сommit
523a01ed0e
10 измененных файлов с 177 добавлено и 104 удалено
  1. 11 11
      src/bin/burn.rs
  2. 6 12
      src/bin/mint.rs
  3. 128 46
      src/bin/tx2.rs
  4. 2 5
      src/bin/vm2.rs
  5. 5 6
      src/bin/vm2_burn.rs
  6. 19 18
      src/circuit/mint_contract.rs
  7. 1 1
      src/crypto/mint_proof.rs
  8. 1 1
      src/lib.rs
  9. 1 1
      src/tx/mod.rs
  10. 3 3
      src/util/mod.rs

+ 11 - 11
src/bin/burn.rs

@@ -34,23 +34,23 @@ use halo2_gadgets::{
 };
 use pasta_curves::{
     arithmetic::{CurveAffine, Field},
-    group::{ff::{PrimeField, PrimeFieldBits}, Curve},
+    group::{
+        ff::{PrimeField, PrimeFieldBits},
+        Curve,
+    },
     pallas,
 };
 use rand::rngs::OsRng;
 
-use drk::{
-    crypto::{
-        constants::{
-            sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION, i2lebsp},
-            OrchardFixedBases,
-        },
-        util::{
-            pedersen_commitment_u64,
-            pedersen_commitment_scalar
+use drk::crypto::{
+    constants::{
+        sinsemilla::{
+            i2lebsp, OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION,
         },
-        proof::{Proof, ProvingKey, VerifyingKey},
+        OrchardFixedBases,
     },
+    proof::{Proof, ProvingKey, VerifyingKey},
+    util::{pedersen_commitment_scalar, pedersen_commitment_u64},
 };
 
 #[derive(Clone, Debug)]

+ 6 - 12
src/bin/mint.rs

@@ -35,18 +35,13 @@ use pasta_curves::{
 };
 use rand::rngs::OsRng;
 
-use drk::{
-    crypto::{
-        constants::{
-            sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
-            OrchardFixedBases,
-        },
-        util::{
-            pedersen_commitment_u64,
-            pedersen_commitment_scalar
-        },
-        proof::{Proof, ProvingKey, VerifyingKey},
+use drk::crypto::{
+    constants::{
+        sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
+        OrchardFixedBases,
     },
+    proof::{Proof, ProvingKey, VerifyingKey},
+    util::{pedersen_commitment_scalar, pedersen_commitment_u64},
 };
 
 #[derive(Clone, Debug)]
@@ -518,4 +513,3 @@ fn main() {
     assert!(proof.verify(&vk, &public_inputs).is_ok());
     println!("Verify: [{:?}]", start.elapsed());
 }
-

+ 128 - 46
src/bin/tx2.rs

@@ -1,6 +1,6 @@
+use log::*;
 use rand::rngs::OsRng;
 use std::{fmt, time::Instant};
-use log::*;
 
 use halo2::{
     circuit::{Layouter, SimpleFloorPlanner},
@@ -32,40 +32,49 @@ use halo2_gadgets::{
 };
 use pasta_curves::{
     arithmetic::{CurveAffine, Field},
-    group::{ff::{PrimeField, PrimeFieldBits}, Curve},
+    group::{
+        ff::{PrimeField, PrimeFieldBits},
+        Curve,
+    },
     pallas,
 };
 
 use drk::{
+    circuit::{mint_contract::MintContract, spend_contract::SpendContract},
     crypto::{
         coin::Coin,
         constants::{
             sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
             OrchardFixedBases,
         },
-        note::{Note, EncryptedNote},
+        note::{EncryptedNote, Note},
         nullifier::Nullifier,
-        util::{
-            pedersen_commitment_u64,
-            pedersen_commitment_scalar
-        },
         proof::{Proof, ProvingKey, VerifyingKey},
         util::mod_r_p,
+        util::{pedersen_commitment_scalar, pedersen_commitment_u64},
     },
 };
 
 struct MemoryState {
+    mint_vk: VerifyingKey,
+    spend_vk: VerifyingKey,
 }
 
 impl ProgramState for MemoryState {
     fn is_valid_cashier_public_key(&self, public: &pallas::Point) -> bool {
         true
     }
+
+    fn mint_vk(&self) -> &VerifyingKey {
+        &self.mint_vk
+    }
+    fn spend_vk(&self) -> &VerifyingKey {
+        &self.spend_vk
+    }
 }
 
 impl MemoryState {
-    fn apply(&mut self, mut update: StateUpdate) {
-    }
+    fn apply(&mut self, mut update: StateUpdate) {}
 }
 
 mod tx2 {
@@ -73,45 +82,45 @@ mod tx2 {
 
     use pasta_curves::{
         arithmetic::{CurveAffine, Field},
-        group::{ff::{PrimeField, PrimeFieldBits}, Curve},
+        group::{
+            ff::{PrimeField, PrimeFieldBits},
+            Curve, Group,
+        },
         pallas,
     };
 
+    use super::{VerifyFailed, VerifyResult};
     use drk::{
         crypto::{
-            mint_proof::{create_mint_proof, MintRevealedValues},
-            proof::Proof,
-            note::{Note, EncryptedNote}
+            mint_proof::{create_mint_proof, verify_mint_proof, MintRevealedValues},
+            note::{EncryptedNote, Note},
+            proof::{Proof, VerifyingKey},
+            util::pedersen_commitment_u64,
         },
         error::Result,
-        types::{
-        DrkValueBlind,
-        DrkSerial,
-        DrkCoinBlind,
-        derive_public_key
-    }};
+        types::{derive_public_key, DrkCoinBlind, DrkSerial, DrkValueBlind, DrkValueCommit},
+    };
 
     type DrkTokenId2 = u64;
 
     pub struct TransactionBuilder {
         pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
         pub inputs: Vec<TransactionBuilderInputInfo>,
-        pub outputs: Vec<TransactionBuilderOutputInfo>
+        pub outputs: Vec<TransactionBuilderOutputInfo>,
     }
 
     pub struct TransactionBuilderClearInputInfo {
         pub value: u64,
         pub token_id: DrkTokenId2,
-        pub signature_secret: pallas::Base
+        pub signature_secret: pallas::Base,
     }
 
-    pub struct TransactionBuilderInputInfo {
-    }
+    pub struct TransactionBuilderInputInfo {}
 
     pub struct TransactionBuilderOutputInfo {
         pub value: u64,
         pub token_id: DrkTokenId2,
-        pub public: pallas::Point
+        pub public: pallas::Point,
     }
 
     impl TransactionBuilder {
@@ -226,7 +235,7 @@ mod tx2 {
         //pub inputs: Vec<PartialTransactionInput>,
         pub outputs: Vec<TransactionOutput>,
     }
-    
+
     pub struct PartialTransactionClearInput {
         pub value: u64,
         pub token_id: DrkTokenId2,
@@ -240,24 +249,77 @@ mod tx2 {
         pub outputs: Vec<TransactionOutput>,
     }
 
+    impl Transaction {
+        fn verify_token_commitments(&self) -> bool {
+            assert_ne!(self.outputs.len(), 0);
+            let token_commit_value = self.outputs[0].revealed.token_commit;
+
+            let mut failed = self
+                .outputs
+                .iter()
+                .any(|output| output.revealed.token_commit != token_commit_value);
+            failed = failed
+                || self.clear_inputs.iter().any(|input| {
+                    pedersen_commitment_u64(input.token_id, input.token_blind) != token_commit_value
+                });
+            !failed
+        }
+
+        pub fn verify(
+            &self,
+            mint_vk: &VerifyingKey,
+            spend_vk: &VerifyingKey,
+        ) -> VerifyResult<()> {
+            let mut valcom_total = DrkValueCommit::identity();
+
+            for input in &self.clear_inputs {
+                valcom_total += pedersen_commitment_u64(input.value, input.value_blind);
+            }
+
+            //for (i, input) in self.inputs.iter().enumerate() {
+            //    if verify_spend_proof(spend_pvk, input.spend_proof.clone(), &input.revealed).is_err() {
+            //        return Err(VerifyFailed::SpendProof(i));
+            //    }
+            //    valcom_total += &input.revealed.value_commit;
+            //}
+
+            for (i, output) in self.outputs.iter().enumerate() {
+                //if verify_mint_proof(mint_vk, &output.mint_proof, &output.revealed).is_err()
+                //{
+                //    return Err(VerifyFailed::MintProof(i));
+                //}
+                valcom_total -= &output.revealed.value_commit;
+            }
+
+            if valcom_total != DrkValueCommit::identity() {
+                return Err(VerifyFailed::MissingFunds);
+            }
+
+            // Verify token commitments match
+            if !self.verify_token_commitments() {
+                return Err(VerifyFailed::TokenMismatch);
+            }
+
+            Ok(())
+        }
+    }
+
     pub struct TransactionClearInput {
         pub value: u64,
-        //pub token_id: DrkTokenId,
-        //pub value_blind: DrkValueBlind,
-        //pub token_blind: DrkValueBlind,
+        pub token_id: DrkTokenId2,
+        pub value_blind: DrkValueBlind,
+        pub token_blind: DrkValueBlind,
         pub signature_public: pallas::Point,
         //pub signature: schnorr::Signature,
     }
 
     impl TransactionClearInput {
-        fn from_partial(
-            partial: PartialTransactionClearInput,
-        ) -> Self {
+        fn from_partial(partial: PartialTransactionClearInput) -> Self {
             Self {
                 value: partial.value,
-                //token_id: partial.token_id,
-                //value_blind: partial.value_blind,
-                //token_blind: partial.token_blind,
+                token_id: partial.token_id,
+                value_blind: partial.value_blind,
+                token_blind: partial.token_blind,
                 signature_public: partial.signature_public,
                 //signature,
             }
@@ -276,8 +338,8 @@ pub trait ProgramState {
     //// TODO: fn is_valid_merkle(&self, merkle: &MerkleNode) -> bool;
     //fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
 
-    //fn mint_pvk(&self) -> &VerifyingKey;
-    //fn spend_pvk(&self) -> &VerifyingKey;
+    fn mint_vk(&self) -> &VerifyingKey;
+    fn spend_vk(&self) -> &VerifyingKey;
 }
 
 pub struct StateUpdate {
@@ -298,7 +360,7 @@ pub enum VerifyFailed {
     ClearInputSignature(usize),
     InputSignature(usize),
     MissingFunds,
-    AssetMismatch,
+    TokenMismatch,
 }
 
 impl std::error::Error for VerifyFailed {}
@@ -324,7 +386,7 @@ impl fmt::Display for VerifyFailed {
             VerifyFailed::MissingFunds => {
                 f.write_str("Money in does not match money out (value commits)")
             }
-            VerifyFailed::AssetMismatch => {
+            VerifyFailed::TokenMismatch => {
                 f.write_str("Assets don't match some inputs or outputs (token commits)")
             }
         }
@@ -351,7 +413,7 @@ pub fn state_transition<S: ProgramState>(
 
     debug!(target: "STATE TRANSITION", "Check the tx Verifies correctly");
     // Check the tx verifies correctly
-    //tx.verify(state.mint_pvk(), state.spend_pvk())?;
+    tx.verify(state.mint_vk(), state.spend_vk())?;
 
     let mut nullifiers = vec![];
 
@@ -367,19 +429,40 @@ pub fn state_transition<S: ProgramState>(
     Ok(StateUpdate {
         nullifiers,
         coins,
-        enc_notes
+        enc_notes,
     })
 }
 
 fn main() -> std::result::Result<(), failure::Error> {
+    use drk::{
+        crypto::mint_proof::{create_mint_proof, verify_mint_proof},
+        types::{DrkSerial, DrkCoinBlind}
+    };
+
     let cashier_secret = pallas::Base::random(&mut OsRng);
     let cashier_public = OrchardFixedBases::SpendAuthG.generator() * mod_r_p(cashier_secret);
 
     let secret = pallas::Base::random(&mut OsRng);
     let public = OrchardFixedBases::SpendAuthG.generator() * mod_r_p(secret);
 
-    let mut state = MemoryState {
-    };
+    let (proof, revealed) = create_mint_proof(
+        110,
+        pallas::Base::from(110),
+        pallas::Scalar::random(&mut OsRng),
+        pallas::Scalar::random(&mut OsRng),
+        DrkSerial::random(&mut OsRng),
+        DrkCoinBlind::random(&mut OsRng),
+        public.clone()
+    )?;
+
+    const K: u32 = 11;
+    let mint_vk = VerifyingKey::build(K, MintContract::default());
+    let spend_vk = VerifyingKey::build(K, SpendContract::default());
+
+    //verify_mint_proof(&mint_vk, &proof, &revealed)?;
+    //println!("DONE!");
+
+    let mut state = MemoryState { mint_vk, spend_vk };
 
     let token_id = 110;
 
@@ -387,14 +470,14 @@ fn main() -> std::result::Result<(), failure::Error> {
         clear_inputs: vec![tx2::TransactionBuilderClearInputInfo {
             value: 110,
             token_id,
-            signature_secret: cashier_secret
+            signature_secret: cashier_secret,
         }],
         inputs: vec![],
         outputs: vec![tx2::TransactionBuilderOutputInfo {
             value: 110,
             token_id,
-            public
-        }]
+            public,
+        }],
     };
 
     let tx = builder.build()?;
@@ -404,4 +487,3 @@ fn main() -> std::result::Result<(), failure::Error> {
 
     Ok(())
 }
-

+ 2 - 5
src/bin/vm2.rs

@@ -43,14 +43,11 @@ use drk::{
             sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
             OrchardFixedBases,
         },
-        util::{
-            pedersen_commitment_u64,
-            pedersen_commitment_scalar
-        },
         proof::{Proof, ProvingKey, VerifyingKey},
+        util::{pedersen_commitment_scalar, pedersen_commitment_u64},
     },
     serial::Decodable,
-    vm2
+    vm2,
 };
 
 fn main() -> std::result::Result<(), failure::Error> {

+ 5 - 6
src/bin/vm2_burn.rs

@@ -42,17 +42,16 @@ use std::{collections::HashMap, fs::File, time::Instant};
 use drk::{
     crypto::{
         constants::{
-            sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION, i2lebsp},
+            sinsemilla::{
+                i2lebsp, OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION,
+            },
             OrchardFixedBases,
         },
-        util::{
-            pedersen_commitment_u64,
-            pedersen_commitment_scalar
-        },
         proof::{Proof, ProvingKey, VerifyingKey},
+        util::{pedersen_commitment_scalar, pedersen_commitment_u64},
     },
     serial::Decodable,
-    vm2
+    vm2,
 };
 
 fn root(path: [pallas::Base; 32], leaf_pos: u32, leaf: pallas::Base) -> pallas::Base {

+ 19 - 18
src/circuit/mint_contract.rs

@@ -1,4 +1,4 @@
-use pasta_curves as pasta;
+use pasta_curves::pallas;
 
 use halo2::{
     circuit::{Layouter, SimpleFloorPlanner},
@@ -42,7 +42,7 @@ pub struct MintConfig {
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     sinsemilla_config_2:
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    poseidon_config: PoseidonConfig<pasta::Fp>,
+    poseidon_config: PoseidonConfig<pallas::Base>,
 }
 
 impl MintConfig {
@@ -50,7 +50,7 @@ impl MintConfig {
         EccChip::construct(self.ecc_config.clone())
     }
 
-    fn poseidon_chip(&self) -> PoseidonChip<pasta::Fp> {
+    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
         PoseidonChip::construct(self.poseidon_config.clone())
     }
 }
@@ -64,21 +64,21 @@ const MINT_ASSCOMY_OFFSET: usize = 4;
 
 #[derive(Default, Debug)]
 pub struct MintContract {
-    pub pub_x: Option<pasta::Fp>,       // x coordinate for pubkey
-    pub pub_y: Option<pasta::Fp>,       // y coordinate for pubkey
-    pub value: Option<pasta::Fp>,       // The value of this coin
-    pub asset: Option<pasta::Fp>,       // The asset ID
-    pub serial: Option<pasta::Fp>,      // Unique serial number corresponding to this coin
-    pub coin_blind: Option<pasta::Fp>,  // Random blinding factor for coin
-    pub value_blind: Option<pasta::Fq>, // Random blinding factor for value commitment
-    pub asset_blind: Option<pasta::Fq>, // Random blinding factor for the asset ID
+    pub pub_x: Option<pallas::Base>,       // x coordinate for pubkey
+    pub pub_y: Option<pallas::Base>,       // y coordinate for pubkey
+    pub value: Option<pallas::Base>,       // The value of this coin
+    pub asset: Option<pallas::Base>,       // The asset ID
+    pub serial: Option<pallas::Base>,      // Unique serial number corresponding to this coin
+    pub coin_blind: Option<pallas::Base>,  // Random blinding factor for coin
+    pub value_blind: Option<pallas::Scalar>, // Random blinding factor for value commitment
+    pub asset_blind: Option<pallas::Scalar>, // Random blinding factor for the asset ID
 }
 
-impl UtilitiesInstructions<pasta::Fp> for MintContract {
-    type Var = CellValue<pasta::Fp>;
+impl UtilitiesInstructions<pallas::Base> for MintContract {
+    type Var = CellValue<pallas::Base>;
 }
 
-impl Circuit<pasta::Fp> for MintContract {
+impl Circuit<pallas::Base> for MintContract {
     type Config = MintConfig;
     type FloorPlanner = SimpleFloorPlanner;
 
@@ -86,7 +86,7 @@ impl Circuit<pasta::Fp> for MintContract {
         Self::default()
     }
 
-    fn configure(meta: &mut ConstraintSystem<pasta::Fp>) -> Self::Config {
+    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
         // Advice columns used in the circuit
         let advices = [
             meta.advice_column(),
@@ -235,7 +235,7 @@ impl Circuit<pasta::Fp> for MintContract {
     fn synthesize(
         &self,
         config: Self::Config,
-        mut layouter: impl Layouter<pasta::Fp>,
+        mut layouter: impl Layouter<pallas::Base>,
     ) -> Result<(), plonk::Error> {
         // Load the Sinsemilla generator lookup table used by the whole circuit.
         SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
@@ -317,7 +317,7 @@ impl Circuit<pasta::Fp> for MintContract {
                     poseidon_message,
                 )?;
 
-                let poseidon_output: CellValue<pasta::Fp> = poseidon_output.inner().into();
+                let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
                 poseidon_output
             };
 
@@ -360,7 +360,7 @@ impl Circuit<pasta::Fp> for MintContract {
         let one = self.load_private(
             layouter.namespace(|| "load constant one"),
             config.advices[0],
-            Some(pasta::Fp::one()),
+            Some(pallas::Base::one()),
         )?;
 
         // v * G_1
@@ -426,3 +426,4 @@ impl Circuit<pasta::Fp> for MintContract {
         Ok(())
     }
 }
+

+ 1 - 1
src/crypto/mint_proof.rs

@@ -146,7 +146,7 @@ pub fn create_mint_proof(
 
 pub fn verify_mint_proof(
     vk: &VerifyingKey,
-    proof: Proof,
+    proof: &Proof,
     revealed: &MintRevealedValues,
 ) -> Result<()> {
     let public_inputs = revealed.make_outputs();

+ 1 - 1
src/lib.rs

@@ -15,8 +15,8 @@ pub mod system;
 pub mod tx;
 pub mod types;
 pub mod util;
-pub mod wallet;
 pub mod vm2;
 pub mod vm2_serial;
+pub mod wallet;
 
 pub use crate::error::{Error, Result};

+ 1 - 1
src/tx/mod.rs

@@ -93,7 +93,7 @@ impl Transaction {
         }
 
         for (i, output) in self.outputs.iter().enumerate() {
-            if verify_mint_proof(mint_pvk, output.mint_proof.clone(), &output.revealed).is_err() {
+            if verify_mint_proof(mint_pvk, &output.mint_proof, &output.revealed).is_err() {
                 return Err(state::VerifyFailed::MintProof(i));
             }
             valcom_total -= &output.revealed.value_commit;

+ 3 - 3
src/util/mod.rs

@@ -1,11 +1,11 @@
+pub mod address;
 pub mod net_name;
 pub mod parse;
 pub mod path;
 pub mod token_list;
-pub mod address;
 
+pub use address::Address;
 pub use net_name::NetworkName;
 pub use parse::{assign_id, decode_base10, encode_base10, generate_id};
-pub use address::Address;
-pub use token_list::{DrkTokenList, TokenList};
 pub use path::{expand_path, join_config_path};
+pub use token_list::{DrkTokenList, TokenList};