Răsfoiți Sursa

working spends for tx builder

narodnik 4 ani în urmă
părinte
comite
c86b8c63fa
7 a modificat fișierele cu 58 adăugiri și 40 ștergeri
  1. 7 3
      src/bin/tx2.rs
  2. 0 5
      src/circuit/spend_contract.rs
  3. 7 5
      src/crypto/schnorr.rs
  4. 36 20
      src/crypto/spend_proof.rs
  5. 4 5
      src/tx/builder.rs
  6. 1 1
      src/tx/mod.rs
  7. 3 1
      src/types.rs

+ 7 - 3
src/bin/tx2.rs

@@ -677,7 +677,7 @@ fn main() -> std::result::Result<(), failure::Error> {
     let cashier_public = cashier_secret.public_key();
 
     let secret = pallas::Base::random(&mut OsRng);
-    let public = OrchardFixedBases::SpendAuthG.generator() * mod_r_p(secret);
+    let public = OrchardFixedBases::NullifierK.generator() * mod_r_p(secret);
 
     const K: u32 = 11;
     let mint_vk = VerifyingKey::build(K, MintContract::default());
@@ -706,7 +706,7 @@ fn main() -> std::result::Result<(), failure::Error> {
     tx.verify(&state.mint_vk, &state.spend_vk)
         .expect("tx verify");
 
-    let mut tree = BridgeTree::<MerkleNode, 2>::new(100);
+    let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
     let node = MerkleNode(tx.outputs[0].revealed.coin.clone());
     tree.append(&node);
     tree.witness();
@@ -746,6 +746,11 @@ fn main() -> std::result::Result<(), failure::Error> {
         }],
     };
 
+    let tx = builder.build()?;
+
+    tx.verify(&state.mint_vk, &state.spend_vk)
+        .expect("tx verify");
+
     let mut tree = BridgeTree::<MerkleNode, 2>::new(100);
     let coin1 = MerkleNode(pallas::Base::random(&mut OsRng));
     let coin2 = MerkleNode(pallas::Base::random(&mut OsRng));
@@ -765,7 +770,6 @@ fn main() -> std::result::Result<(), failure::Error> {
     let current = MerkleNode::combine(0.into(), &coin3, &path[0]);
     let root2 = MerkleNode::combine(1.into(), &path[1], &current);
     assert_eq!(root2, tree.root());
-    println!("{}", u64::from(position));
 
     let position: u64 = position.into();
     let mut current = coin3;

+ 0 - 5
src/circuit/spend_contract.rs

@@ -429,11 +429,6 @@ impl Circuit<pasta::Fp> for SpendContract {
         // ===========
         // Merkle root
         // ===========
-        //let leaf = self.load_private(
-        //    layouter.namespace(|| "load leaf"),
-        //    config.advices[0],
-        //    self.leaf,
-        //)?;
 
         let path = MerklePath {
             chip_1: merkle_chip_1,

+ 7 - 5
src/crypto/schnorr.rs

@@ -1,7 +1,7 @@
 use std::io;
 
 use halo2_gadgets::ecc::FixedPoints;
-use pasta_curves::{arithmetic::Field, group::GroupEncoding};
+use pasta_curves::{arithmetic::Field, group::GroupEncoding, pallas};
 use rand::rngs::OsRng;
 
 use super::{
@@ -17,11 +17,12 @@ use crate::{
     },
 };
 
-pub struct SecretKey(pub DrkSecretKey);
+#[derive(Clone)]
+pub struct SecretKey(pub pallas::Scalar);
 
 impl SecretKey {
     pub fn random() -> Self {
-        Self(DrkSecretKey::random(&mut OsRng))
+        Self(pallas::Scalar::random(&mut OsRng))
     }
 
     pub fn sign(&self, message: &[u8]) -> Signature {
@@ -29,13 +30,14 @@ impl SecretKey {
         let commit = OrchardFixedBases::SpendAuthG.generator() * mask;
 
         let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
-        let response = mask + challenge * mod_r_p(self.0);
+        let response = mask + challenge * self.0;
 
         Signature { commit, response }
     }
 
     pub fn public_key(&self) -> PublicKey {
-        PublicKey(derive_public_key(self.0))
+        let public_key = OrchardFixedBases::SpendAuthG.generator() * self.0;
+        PublicKey(public_key)
     }
 }
 

+ 36 - 20
src/crypto/spend_proof.rs

@@ -11,6 +11,7 @@ use pasta_curves::{
     group::Curve,
     pallas,
 };
+use incrementalmerkletree::Hashable;
 
 use super::{
     nullifier::Nullifier,
@@ -19,7 +20,7 @@ use super::{
 };
 use crate::{
     circuit::spend_contract::SpendContract,
-    crypto::merkle_node2::MerkleNode,
+    crypto::{merkle_node2::MerkleNode, schnorr},
     serial::{Decodable, Encodable},
     types::*,
     Result,
@@ -29,8 +30,8 @@ pub struct SpendRevealedValues {
     pub value_commit: DrkValueCommit,
     pub token_commit: DrkValueCommit,
     pub nullifier: Nullifier,
-    //pub merkle_root: MerkleNode,
-    pub signature_public: DrkPublicKey,
+    pub merkle_root: MerkleNode,
+    pub signature_public: schnorr::PublicKey,
 }
 
 impl SpendRevealedValues {
@@ -43,8 +44,9 @@ impl SpendRevealedValues {
         serial: DrkSerial,
         coin_blind: DrkCoinBlind,
         secret: DrkSecretKey,
-        merkle_path: Vec<DrkCoin>,
-        signature_secret: DrkSecretKey,
+        leaf_position: incrementalmerkletree::Position,
+        merkle_path: Vec<MerkleNode>,
+        signature_secret: schnorr::SecretKey,
     ) -> Self {
         let nullifier = [secret, serial];
         let nullifier =
@@ -63,34 +65,46 @@ impl SpendRevealedValues {
             coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
         }
 
-        // TODO: Merkle root
+        let merkle_root = {
+        let position: u64 = leaf_position.into();
+        let mut current = MerkleNode(coin);
+        for (level, sibling) in merkle_path.iter().enumerate() {
+            let level = level as u8;
+            current = 
+                if position & (1 << level) == 0 {
+                    MerkleNode::combine(level.into(), &current, sibling)
+                } else {
+                    MerkleNode::combine(level.into(), sibling, &current)
+                };
+        }
+        current
+        };
 
         let value_commit = pedersen_commitment_u64(value, value_blind);
         let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
 
-        let signature_public = derive_public_key(signature_secret);
-
         SpendRevealedValues {
             value_commit,
             token_commit,
             nullifier: Nullifier(nullifier),
-            signature_public,
+            merkle_root,
+            signature_public: signature_secret.public_key(),
         }
     }
 
     fn make_outputs(&self) -> [DrkCircuitField; 8] {
         let value_coords = self.value_commit.to_affine().coordinates().unwrap();
         let token_coords = self.token_commit.to_affine().coordinates().unwrap();
-        let sig_coords = self.signature_public.to_affine().coordinates().unwrap();
+        let merkle_root = self.merkle_root.0;
+        let sig_coords = self.signature_public.0.to_affine().coordinates().unwrap();
 
-        // TODO: merkle
         vec![
             self.nullifier.inner(),
             *value_coords.x(),
             *value_coords.y(),
             *token_coords.x(),
             *token_coords.y(),
-            // merkleroot,
+            merkle_root,
             *sig_coords.x(),
             *sig_coords.y(),
         ]
@@ -105,7 +119,7 @@ impl Encodable for SpendRevealedValues {
         len += self.value_commit.encode(&mut s)?;
         len += self.token_commit.encode(&mut s)?;
         len += self.nullifier.encode(&mut s)?;
-        //len += self.merkle_root.encode(&mut s)?;
+        len += self.merkle_root.encode(&mut s)?;
         len += self.signature_public.encode(s)?;
         Ok(len)
     }
@@ -117,7 +131,7 @@ impl Decodable for SpendRevealedValues {
             value_commit: Decodable::decode(&mut d)?,
             token_commit: Decodable::decode(&mut d)?,
             nullifier: Decodable::decode(&mut d)?,
-            //merkle_root: Decodable::decode(&mut d)?,
+            merkle_root: Decodable::decode(&mut d)?,
             signature_public: Decodable::decode(d)?,
         })
     }
@@ -132,14 +146,12 @@ pub fn create_spend_proof(
     serial: DrkSerial,
     coin_blind: DrkCoinBlind,
     secret: DrkSecretKey,
-    leaf_position: u64,
+    leaf_position: incrementalmerkletree::Position,
     merkle_path: Vec<MerkleNode>,
-    signature_secret: DrkSecretKey,
+    signature_secret: schnorr::SecretKey,
 ) -> Result<(Proof, SpendRevealedValues)> {
     const K: u32 = 11;
 
-    let merkle_path: Vec<pallas::Base> = merkle_path.iter().map(|node| node.0).collect();
-
     let revealed = SpendRevealedValues::compute(
         value,
         token_id,
@@ -148,10 +160,14 @@ pub fn create_spend_proof(
         serial,
         coin_blind,
         secret,
+        leaf_position,
         merkle_path.clone(),
-        signature_secret,
+        signature_secret.clone(),
     );
 
+    let merkle_path: Vec<pallas::Base> = merkle_path.iter().map(|node| node.0).collect();
+    let leaf_position: u64 = leaf_position.into();
+
     let c = SpendContract {
         secret_key: Some(secret),
         serial: Some(serial),
@@ -162,7 +178,7 @@ pub fn create_spend_proof(
         asset_blind: Some(token_blind),
         leaf_pos: Some(leaf_position as u32),
         merkle_path: Some(merkle_path.try_into().unwrap()),
-        sig_secret: Some(mod_r_p(signature_secret)),
+        sig_secret: Some(signature_secret.0),
     };
 
     let start = Instant::now();

+ 4 - 5
src/tx/builder.rs

@@ -86,7 +86,7 @@ impl TransactionBuilder {
         for input in self.inputs {
             input_blinds.push(input.note.value_blind);
 
-            let signature_secret = DrkSecretKey::random(&mut OsRng);
+            let signature_secret = schnorr::SecretKey::random();
 
             let (proof, revealed) = create_spend_proof(
                 input.note.value,
@@ -96,13 +96,12 @@ impl TransactionBuilder {
                 input.note.serial,
                 input.note.coin_blind,
                 input.secret,
-                input.leaf_position.into(),
+                input.leaf_position,
                 input.merkle_path,
-                signature_secret,
+                signature_secret.clone(),
             )?;
 
             // First we make the tx then sign after
-            let signature_secret = schnorr::SecretKey(signature_secret);
             signature_secrets.push(signature_secret);
 
             let input = PartialTransactionInput {
@@ -146,7 +145,7 @@ impl TransactionBuilder {
                 value_blind,
             };
 
-            let encrypted_note = note.encrypt(&output.public).unwrap();
+            let encrypted_note = note.encrypt(&output.public)?;
 
             let output = TransactionOutput {
                 mint_proof,

+ 1 - 1
src/tx/mod.rs

@@ -132,7 +132,7 @@ impl Transaction {
             }
         }
         for (i, input) in self.inputs.iter().enumerate() {
-            let public = schnorr::PublicKey(input.revealed.signature_public);
+            let public = &input.revealed.signature_public;
             if !public.verify(&unsigned_tx_data[..], &input.signature) {
                 return Err(state::VerifyFailed::InputSignature(i));
             }

+ 3 - 1
src/types.rs

@@ -23,6 +23,8 @@ pub type DrkValueCommit = pallas::Point;
 pub type DrkPublicKey = pallas::Point;
 pub type DrkSecretKey = pallas::Base;
 
+// TODO: move this elsewhere
 pub fn derive_public_key(s: DrkSecretKey) -> DrkPublicKey {
-    OrchardFixedBases::SpendAuthG.generator() * mod_r_p(s)
+    OrchardFixedBases::NullifierK.generator() * mod_r_p(s)
 }
+