Преглед изворни кода

Use the new keypair module throughout the codebase.

parazyd пре 4 година
родитељ
комит
ff01e7b685

+ 18 - 11
src/bin/cashierd.rs

@@ -7,7 +7,7 @@ use clap::clap_app;
 use easy_parallel::Parallel;
 use incrementalmerkletree::bridgetree::BridgeTree;
 use log::{debug, info};
-use pasta_curves::pallas;
+use rand::rngs::OsRng;
 use serde_json::{json, Value};
 
 use drk::{
@@ -15,7 +15,11 @@ use drk::{
     circuit::{MintContract, SpendContract},
     cli::{CashierdConfig, Config},
     client::Client,
-    crypto::{merkle_node::MerkleNode, proof::VerifyingKey, schnorr},
+    crypto::{
+        keypair::{PublicKey, SecretKey},
+        merkle_node::MerkleNode,
+        proof::VerifyingKey,
+    },
     rpc::{
         jsonrpc::{error as jsonerr, response as jsonresp, ErrorCode::*, JsonRequest, JsonResult},
         rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
@@ -25,7 +29,10 @@ use drk::{
     state::State,
     types::DrkTokenId,
     util::{expand_path, generate_id, join_config_path, parse::truncate, NetworkName},
-    wallet::{cashierdb::TokenKey, CashierDb, WalletDb},
+    wallet::{
+        cashierdb::{CashierDb, TokenKey},
+        walletdb::WalletDb,
+    },
     Error, Result,
 };
 
@@ -103,7 +110,7 @@ impl Cashierd {
     async fn listen_for_receiving_coins(
         bridge: Arc<Bridge>,
         cashier_wallet: Arc<CashierDb>,
-        recv_coin: async_channel::Receiver<(pallas::Point, u64)>,
+        recv_coin: async_channel::Receiver<(PublicKey, u64)>,
         executor: Arc<Executor<'_>>,
     ) -> Result<()> {
         // received drk coin
@@ -208,7 +215,7 @@ impl Cashierd {
                 mint_address = "";
             }
             let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
-            let drk_pub_key: pallas::Point = deserialize(&drk_pub_key)?;
+            let drk_pub_key: PublicKey = deserialize(&drk_pub_key)?;
 
             // check if the drk public key already exist
             let check = self
@@ -336,7 +343,7 @@ impl Cashierd {
 
             let address = serialize(&address.to_string());
 
-            let cashier_public: pallas::Point;
+            let cashier_public: PublicKey;
 
             if let Some(addr) = self
                 .cashier_wallet
@@ -345,14 +352,14 @@ impl Cashierd {
             {
                 cashier_public = addr.public;
             } else {
-                let cashier_secret = schnorr::SecretKey::random();
-                cashier_public = cashier_secret.public_key().inner();
+                let cashier_secret = SecretKey::random(&mut OsRng);
+                cashier_public = PublicKey::from_secret(cashier_secret);
 
                 self.cashier_wallet
                     .put_withdraw_keys(
                         &address,
                         &cashier_public,
-                        &cashier_secret.inner(),
+                        &cashier_secret,
                         &network,
                         &token_id,
                         mint_address.into(),
@@ -601,7 +608,7 @@ impl Cashierd {
 
         client.start().await?;
 
-        let (notify, recv_coin) = async_channel::unbounded::<(pallas::Point, u64)>();
+        let (notify, recv_coin) = async_channel::unbounded::<(PublicKey, u64)>();
 
         client
             .connect_to_subscriber_from_cashier(
@@ -703,9 +710,9 @@ async fn start(
         tree: BridgeTree::<MerkleNode, 32>::new(100),
         merkle_roots,
         nullifiers,
+        public_keys: cashier_public_keys,
         mint_vk,
         spend_vk,
-        public_keys: cashier_public_keys,
     }));
 
     if get_address_flag {

+ 7 - 7
src/bin/darkfid.rs

@@ -17,7 +17,7 @@ use drk::{
     circuit::{MintContract, SpendContract},
     cli::{Config, DarkfidConfig},
     client::Client,
-    crypto::{merkle_node::MerkleNode, proof::VerifyingKey},
+    crypto::{keypair::PublicKey, merkle_node::MerkleNode, proof::VerifyingKey},
     rpc::{
         jsonrpc::{
             error as jsonerr, request as jsonreq, response as jsonresp, send_raw_request,
@@ -31,7 +31,7 @@ use drk::{
         assign_id, decode_base10, encode_base10, expand_path, join_config_path, DrkTokenList,
         NetworkName, TokenList,
     },
-    wallet::WalletDb,
+    wallet::walletdb::WalletDb,
     Error, Result,
 };
 
@@ -39,7 +39,7 @@ use drk::{
 pub struct Cashier {
     pub name: String,
     pub rpc_url: String,
-    pub public_key: pallas::Point,
+    pub public_key: PublicKey,
 }
 
 #[async_trait]
@@ -424,7 +424,7 @@ impl Darkfid {
             let result: Result<()> = async {
                 let cashier_public = cashier_public.result.as_str().unwrap();
 
-                let cashier_public: pallas::Point =
+                let cashier_public: PublicKey =
                     deserialize(&bs58::decode(cashier_public).into_vec()?)?;
 
                 self.client
@@ -509,7 +509,7 @@ impl Darkfid {
 
         let result: Result<()> = async {
             let drk_address = bs58::decode(&address).into_vec()?;
-            let drk_address: pallas::Point = deserialize(&drk_address)?;
+            let drk_address: PublicKey = deserialize(&drk_address)?;
 
             let decimals: usize = 8;
             let amount = decode_base10(amount, decimals, true)?;
@@ -546,7 +546,7 @@ async fn start(
     let mut cashier_keys = Vec::new();
 
     if let Some(cpub) = local_cashier {
-        let cashier_public: pallas::Point = deserialize(&bs58::decode(cpub).into_vec()?)?;
+        let cashier_public: PublicKey = deserialize(&bs58::decode(cpub).into_vec()?)?;
 
         cashiers.push(Cashier {
             name: "localCashier".into(),
@@ -561,7 +561,7 @@ async fn start(
                 return Err(Error::CashierKeysNotFound)
             }
 
-            let cashier_public: pallas::Point =
+            let cashier_public: PublicKey =
                 deserialize(&bs58::decode(cashier.public_key).into_vec()?)?;
 
             cashiers.push(Cashier {

+ 13 - 14
src/bin/tx2.rs

@@ -6,12 +6,11 @@ use drk::{
     circuit::{mint_contract::MintContract, spend_contract::SpendContract},
     crypto::{
         coin::Coin,
-        keypair::Keypair,
+        keypair::{Keypair, PublicKey, SecretKey},
         merkle_node::MerkleNode,
         note::{EncryptedNote, Note},
         nullifier::Nullifier,
         proof::VerifyingKey,
-        schnorr,
     },
     state::{state_transition, ProgramState, StateUpdate},
     tx, Result,
@@ -35,13 +34,13 @@ struct MemoryState {
     spend_vk: VerifyingKey,
 
     // Public key of the cashier
-    cashier_signature_public: schnorr::PublicKey,
+    cashier_signature_public: PublicKey,
     // List of all our secret keys
-    secrets: Vec<pallas::Base>,
+    secrets: Vec<SecretKey>,
 }
 
 impl ProgramState for MemoryState {
-    fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool {
+    fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
         public == &self.cashier_signature_public
     }
 
@@ -73,7 +72,7 @@ impl MemoryState {
             let node = MerkleNode(coin.0);
             self.tree.append(&node);
 
-            //// Keep track of all merkle roots that have existed
+            // Keep track of all merkle roots that have existed
             self.merkle_roots.push(self.tree.root());
 
             if let Some((note, _secret)) = self.try_decrypt_note(enc_note) {
@@ -83,7 +82,7 @@ impl MemoryState {
         }
     }
 
-    fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, pallas::Base)> {
+    fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, SecretKey)> {
         // Loop through all our secret keys...
         for secret in &self.secrets {
             // ... attempt to decrypt the note ...
@@ -98,8 +97,8 @@ impl MemoryState {
 }
 
 fn main() -> Result<()> {
-    let cashier_signature_secret = schnorr::SecretKey::random();
-    let cashier_signature_public = cashier_signature_secret.public_key();
+    let cashier_signature_secret = SecretKey::random(&mut OsRng);
+    let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
 
     let keypair = Keypair::random(&mut OsRng);
 
@@ -115,7 +114,7 @@ fn main() -> Result<()> {
         mint_vk,
         spend_vk,
         cashier_signature_public,
-        secrets: vec![keypair.secret.inner()],
+        secrets: vec![keypair.secret],
     };
 
     let token_id = pallas::Base::from(110);
@@ -130,7 +129,7 @@ fn main() -> Result<()> {
         outputs: vec![tx::TransactionBuilderOutputInfo {
             value: 110,
             token_id,
-            public: keypair.public.inner(),
+            public: keypair.public,
         }],
     };
 
@@ -138,7 +137,7 @@ fn main() -> Result<()> {
 
     tx.verify(&state.mint_vk, &state.spend_vk).expect("tx verify");
 
-    let _note = tx.outputs[0].enc_note.decrypt(&keypair.secret.inner())?;
+    let _note = tx.outputs[0].enc_note.decrypt(&keypair.secret)?;
 
     let update = state_transition(&state, tx)?;
     state.apply(update);
@@ -153,13 +152,13 @@ fn main() -> Result<()> {
         inputs: vec![tx::TransactionBuilderInputInfo {
             leaf_position,
             merkle_path,
-            secret: keypair.secret.inner(),
+            secret: keypair.secret,
             note: note.clone(),
         }],
         outputs: vec![tx::TransactionBuilderOutputInfo {
             value: 110,
             token_id,
-            public: keypair.public.inner(),
+            public: keypair.public,
         }],
     };
 

+ 12 - 6
src/circuit/spend_contract.rs

@@ -102,7 +102,8 @@ pub struct SpendContract {
     pub asset_blind: Option<pallas::Scalar>,
     pub leaf_pos: Option<u32>,
     pub merkle_path: Option<[pallas::Base; 32]>,
-    pub sig_secret: Option<pallas::Scalar>,
+    //pub sig_secret: Option<pallas::Scalar>,
+    pub sig_secret: Option<pallas::Base>,
 }
 
 impl UtilitiesInstructions<pallas::Base> for SpendContract {
@@ -442,11 +443,16 @@ impl Circuit<pallas::Base> for SpendContract {
         // ========================
         // Signature key derivation
         // ========================
-        let (sig_pub, _) = {
-            let spend_auth_g = OrchardFixedBases::SpendAuthG;
-            let spend_auth_g = FixedPoint::from_inner(ecc_chip, spend_auth_g);
-            // TODO: Do we need to load sig_secret somewhere first?
-            spend_auth_g.mul(layouter.namespace(|| "[x_s] SpendAuthG"), self.sig_secret)?
+        let sig_secret = self.load_private(
+            layouter.namespace(|| "load sig_secret"),
+            config.advices[0],
+            self.sig_secret,
+        )?;
+
+        let sig_pub = {
+            let nullifier_k = OrchardFixedBases::NullifierK;
+            let nullifier_k = FixedPoint::from_inner(ecc_chip.clone(), nullifier_k);
+            nullifier_k.mul_base_field(layouter.namespace(|| "[x_s] Nullifier"), sig_secret)?
         };
 
         layouter.constrain_instance(

+ 22 - 15
src/client.rs

@@ -7,12 +7,20 @@ use url::Url;
 
 use crate::{
     blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
-    crypto::{coin::Coin, merkle_node::MerkleNode, schnorr, util::mod_r_p, OwnCoin},
+    crypto::{
+        coin::Coin,
+        keypair::{Keypair, PublicKey, SecretKey},
+        merkle_node::MerkleNode,
+        OwnCoin,
+    },
     serial::{serialize, Decodable, Encodable},
     service::GatewayClient,
     state::{state_transition, State},
     tx,
-    wallet::{walletdb::Balances, CashierDbPtr, Keypair, WalletPtr},
+    wallet::{
+        cashierdb::CashierDbPtr,
+        walletdb::{Balances, WalletPtr},
+    },
     Result,
 };
 
@@ -95,7 +103,7 @@ impl Client {
 
     async fn build_slab_from_tx(
         &mut self,
-        pubkey: pallas::Point,
+        pubkey: PublicKey,
         value: u64,
         token_id: pallas::Base,
         clear_input: bool,
@@ -109,8 +117,9 @@ impl Client {
 
         if clear_input {
             // TODO: FIXME:
-            let base_secret = self.main_keypair.secret;
-            let signature_secret = schnorr::SecretKey(mod_r_p(base_secret));
+            let signature_secret = self.main_keypair.clone().secret;
+            let signature_public = PublicKey::from_secret(signature_secret);
+            debug!("SIGNATURE PUBLIC: {:?}", signature_public);
             let input = tx::TransactionBuilderClearInputInfo { value, token_id, signature_secret };
             clear_inputs.push(input);
         } else {
@@ -124,7 +133,7 @@ impl Client {
                     break
                 }
 
-                let node = MerkleNode(own_coin.coin.inner());
+                let node = MerkleNode(own_coin.coin.0);
                 let (leaf_position, merkle_path) = state_m.tree.authentication_path(&node).unwrap();
                 // TODO: What is this counting? Is it everything or does it know to separate
                 // different tokens?
@@ -179,7 +188,7 @@ impl Client {
 
     pub async fn send(
         &mut self,
-        pubkey: pallas::Point,
+        pubkey: PublicKey,
         amount: u64,
         token_id: pallas::Base,
         clear_input: bool,
@@ -204,7 +213,7 @@ impl Client {
     pub async fn transfer(
         &mut self,
         token_id: pallas::Base,
-        pubkey: pallas::Point,
+        pubkey: PublicKey,
         amount: u64,
         state: Arc<Mutex<State>>,
     ) -> ClientResult<()> {
@@ -222,11 +231,11 @@ impl Client {
     }
 
     async fn update_state(
-        secret_keys: Vec<pallas::Base>,
+        secret_keys: Vec<SecretKey>,
         slab: &Slab,
         state: Arc<Mutex<State>>,
         wallet: WalletPtr,
-        notify: Option<async_channel::Sender<(pallas::Point, u64)>>,
+        notify: Option<async_channel::Sender<(PublicKey, u64)>>,
     ) -> Result<()> {
         debug!("Build tx from slab and update the state");
         let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
@@ -242,7 +251,7 @@ impl Client {
         &self,
         state: Arc<Mutex<State>>,
         cashier_wallet: CashierDbPtr,
-        notify: async_channel::Sender<(pallas::Point, u64)>,
+        notify: async_channel::Sender<(PublicKey, u64)>,
         executor: Arc<Executor<'_>>,
     ) -> Result<()> {
         debug!("Start subscriber for cashier");
@@ -251,13 +260,12 @@ impl Client {
         let secret_key = self.main_keypair.secret;
         let wallet = self.wallet.clone();
 
-        //let task: smol::Task<Result<()>> = executor.spawn(async move {
         let task: smol::Task<Result<()>> = executor.spawn(async move {
             loop {
                 let slab = gateway_slabs_sub.recv().await?;
                 debug!("Received new slab");
 
-                let mut secret_keys: Vec<pallas::Base> = vec![secret_key];
+                let mut secret_keys = vec![secret_key];
                 let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys().await?;
                 secret_keys.append(&mut withdraw_keys);
 
@@ -289,8 +297,7 @@ impl Client {
         debug!("Start subscriber for darkfid");
         let gateway_slabs_sub = self.gateway.start_subscriber(executor.clone()).await?;
 
-        let secret_key = self.main_keypair.secret;
-
+        let secret_key = self.main_keypair.secret.clone();
         let wallet = self.wallet.clone();
 
         let task: smol::Task<Result<()>> = executor.spawn(async move {

+ 0 - 4
src/crypto/coin.rs

@@ -18,10 +18,6 @@ impl Coin {
     pub fn to_bytes(self) -> [u8; 32] {
         self.0.to_bytes()
     }
-
-    pub(crate) fn inner(&self) -> pallas::Base {
-        self.0
-    }
 }
 
 impl Encodable for Coin {

+ 11 - 6
src/crypto/diffie_hellman.rs

@@ -1,7 +1,11 @@
 use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
-use pasta_curves as pasta;
 use pasta_curves::group::{cofactor::CofactorGroup, GroupEncoding};
 
+use crate::crypto::{
+    keypair::{PublicKey, SecretKey},
+    util::mod_r_p,
+};
+
 pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
 
 /// Functions used for encrypting the note in transaction outputs.
@@ -9,7 +13,7 @@ pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
 /// Sapling key agreement for note encryption.
 ///
 /// Implements section 5.4.4.3 of the Zcash Protocol Specification.
-pub fn sapling_ka_agree(esk: &pasta::Fq, pk_d: &pasta::Ep) -> pasta::Ep {
+pub fn sapling_ka_agree(esk: &SecretKey, pk_d: &PublicKey) -> PublicKey {
     // [8 esk] pk_d
     // <ExtendedPoint as CofactorGroup>::clear_cofactor is implemented using
     // ExtendedPoint::mul_by_cofactor in the jubjub crate.
@@ -19,19 +23,20 @@ pub fn sapling_ka_agree(esk: &pasta::Fq, pk_d: &pasta::Ep) -> pasta::Ep {
     // of bits instead of individual bits).
     // We want that to be fast because it's in the hot path for trial decryption of
     // notes on chain.
+    let esk_s = mod_r_p(esk.0);
     let mut wnaf = group::Wnaf::new();
-    wnaf.scalar(esk).base(*pk_d).clear_cofactor()
+    PublicKey(wnaf.scalar(&esk_s).base(pk_d.0).clear_cofactor())
 }
 
 /// Sapling KDF for note encryption.
 ///
 /// Implements section 5.4.4.4 of the Zcash Protocol Specification.
-pub fn kdf_sapling(dhsecret: pasta::Ep, epk: &pasta::Ep) -> Blake2bHash {
+pub fn kdf_sapling(dhsecret: &PublicKey, epk: &PublicKey) -> Blake2bHash {
     Blake2bParams::new()
         .hash_length(32)
         .personal(KDF_SAPLING_PERSONALIZATION)
         .to_state()
-        .update(&dhsecret.to_bytes())
-        .update(&epk.to_bytes())
+        .update(&dhsecret.0.to_bytes())
+        .update(&epk.0.to_bytes())
         .finalize()
 }

+ 134 - 18
src/crypto/keypair.rs

@@ -1,22 +1,28 @@
+use std::io;
+
 use halo2_gadgets::ecc::FixedPoints;
-use pasta_curves::{arithmetic::Field, pallas};
+use pasta_curves::{
+    arithmetic::{Field, FieldExt},
+    group::{Group, GroupEncoding},
+    pallas,
+};
 use rand::RngCore;
 
-use crate::crypto::{constants::OrchardFixedBases, util::mod_r_p};
+use crate::{
+    crypto::{constants::OrchardFixedBases, util::mod_r_p},
+    serial::{Decodable, Encodable, ReadExt, WriteExt},
+    Error, Result,
+};
 
-#[derive(Clone, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Keypair {
     pub secret: SecretKey,
     pub public: PublicKey,
 }
 
 impl Keypair {
-    fn derive_public_key(s: SecretKey) -> PublicKey {
-        PublicKey(OrchardFixedBases::NullifierK.generator() * mod_r_p(s.inner()))
-    }
-
     pub fn new(secret: SecretKey) -> Self {
-        let public = Keypair::derive_public_key(secret.clone());
+        let public = PublicKey::from_secret(secret.clone());
         Keypair { secret, public }
     }
 
@@ -26,25 +32,135 @@ impl Keypair {
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct SecretKey(pallas::Base);
+#[derive(Copy, Clone, Debug)]
+pub struct SecretKey(pub pallas::Base);
 
 impl SecretKey {
-    pub fn inner(&self) -> pallas::Base {
-        self.0
-    }
-
     pub fn random(mut rng: impl RngCore) -> Self {
         let x = pallas::Base::random(&mut rng);
         SecretKey(x)
     }
+
+    pub fn to_bytes(self) -> [u8; 32] {
+        self.0.to_bytes()
+    }
 }
 
-#[derive(Clone, Debug)]
-pub struct PublicKey(pallas::Point);
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct PublicKey(pub pallas::Point);
 
 impl PublicKey {
-    pub fn inner(&self) -> pallas::Point {
-        self.0
+    pub fn random(mut rng: impl RngCore) -> Self {
+        let p = pallas::Point::random(&mut rng);
+        PublicKey(p)
+    }
+
+    pub fn from_secret(s: SecretKey) -> Self {
+        let p = OrchardFixedBases::NullifierK.generator() * mod_r_p(s.0);
+        PublicKey(p)
+    }
+
+    pub fn to_bytes(self) -> [u8; 32] {
+        self.0.to_bytes()
+    }
+}
+
+impl Encodable for pallas::Base {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        s.write_slice(&self.to_bytes()[..])?;
+        Ok(32)
+    }
+}
+
+impl Decodable for pallas::Base {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice(&mut bytes)?;
+        let result = pallas::Base::from_bytes(&bytes);
+        if result.is_some().into() {
+            Ok(result.unwrap())
+        } else {
+            Err(Error::BadOperationType)
+        }
+    }
+}
+
+impl Encodable for pallas::Scalar {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        s.write_slice(&self.to_bytes()[..])?;
+        Ok(32)
+    }
+}
+
+impl Decodable for pallas::Scalar {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice(&mut bytes)?;
+        let result = pallas::Scalar::from_bytes(&bytes);
+        if result.is_some().into() {
+            Ok(result.unwrap())
+        } else {
+            Err(Error::BadOperationType)
+        }
+    }
+}
+
+impl Encodable for pallas::Point {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        s.write_slice(&self.to_bytes()[..])?;
+        Ok(32)
+    }
+}
+
+impl Decodable for pallas::Point {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice(&mut bytes)?;
+        let result = Self::from_bytes(&bytes);
+        if result.is_some().into() {
+            Ok(result.unwrap())
+        } else {
+            Err(Error::BadOperationType)
+        }
+    }
+}
+
+impl Encodable for SecretKey {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        s.write_slice(&self.0.to_bytes()[..])?;
+        Ok(32)
+    }
+}
+
+impl Decodable for SecretKey {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice(&mut bytes)?;
+        let result = pallas::Base::from_bytes(&bytes);
+        if result.is_some().into() {
+            Ok(SecretKey(result.unwrap()))
+        } else {
+            Err(Error::BadOperationType)
+        }
+    }
+}
+
+impl Encodable for PublicKey {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        s.write_slice(&self.0.to_bytes()[..])?;
+        Ok(32)
+    }
+}
+
+impl Decodable for PublicKey {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice(&mut bytes)?;
+        let result = pallas::Point::from_bytes(&bytes);
+        if result.is_some().into() {
+            Ok(PublicKey(result.unwrap()))
+        } else {
+            Err(Error::BadOperationType)
+        }
     }
 }

+ 16 - 25
src/crypto/mint_proof.rs

@@ -8,15 +8,16 @@ use log::debug;
 use pasta_curves::{
     arithmetic::{CurveAffine, FieldExt},
     group::Curve,
-    pallas,
 };
 
-use super::{
-    proof::{Proof, ProvingKey, VerifyingKey},
-    util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
-};
 use crate::{
     circuit::mint_contract::MintContract,
+    crypto::{
+        coin::Coin,
+        keypair::PublicKey,
+        proof::{Proof, ProvingKey, VerifyingKey},
+        util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
+    },
     serial::{Decodable, Encodable},
     types::*,
     Result,
@@ -42,8 +43,7 @@ impl MintProofKeys {
 pub struct MintRevealedValues {
     pub value_commit: DrkValueCommit,
     pub token_commit: DrkValueCommit,
-    //pub coin: [u8; 32],
-    pub coin: pallas::Base,
+    pub coin: Coin,
 }
 
 impl MintRevealedValues {
@@ -54,26 +54,18 @@ impl MintRevealedValues {
         token_blind: DrkValueBlind,
         serial: DrkSerial,
         coin_blind: DrkCoinBlind,
-        public_key: DrkPublicKey,
+        public_key: PublicKey,
     ) -> Self {
         let value_commit = pedersen_commitment_u64(value, value_blind);
         let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
 
-        let coords = public_key.to_affine().coordinates().unwrap();
-        let messages = [
-            [*coords.x(), *coords.y()],
-            [DrkValue::from_u64(value), token_id],
-            [serial, coin_blind],
-        ];
-
-        let mut coin = DrkCoin::zero();
-        for msg in messages.iter() {
-            coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
-        }
+        let coords = public_key.0.to_affine().coordinates().unwrap();
+        let messages =
+            [*coords.x(), *coords.y(), DrkValue::from_u64(value), token_id, serial, coin_blind];
 
-        //let coin = hash.to_bytes();
+        let coin = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages);
 
-        MintRevealedValues { value_commit, token_commit, coin }
+        MintRevealedValues { value_commit, token_commit, coin: Coin(coin) }
     }
 
     fn make_outputs(&self) -> [DrkCircuitField; 5] {
@@ -81,8 +73,7 @@ impl MintRevealedValues {
         let token_coords = self.token_commit.to_affine().coordinates().unwrap();
 
         vec![
-            //DrkCircuitField::from_bytes(&self.coin).unwrap(),
-            self.coin,
+            self.coin.0,
             *value_coords.x(),
             *value_coords.y(),
             *token_coords.x(),
@@ -121,7 +112,7 @@ pub fn create_mint_proof(
     token_blind: DrkValueBlind,
     serial: DrkSerial,
     coin_blind: DrkCoinBlind,
-    public_key: DrkPublicKey,
+    public_key: PublicKey,
 ) -> Result<(Proof, MintRevealedValues)> {
     const K: u32 = 11;
 
@@ -135,7 +126,7 @@ pub fn create_mint_proof(
         public_key,
     );
 
-    let coords = public_key.to_affine().coordinates().unwrap();
+    let coords = public_key.0.to_affine().coordinates().unwrap();
 
     let c = MintContract {
         pub_x: Some(*coords.x()),

+ 2 - 3
src/crypto/mod.rs

@@ -7,7 +7,6 @@ pub mod merkle_node;
 pub mod mint_proof;
 pub mod note;
 pub mod nullifier;
-pub mod pasta_serial;
 pub mod proof;
 pub mod schnorr;
 pub mod spend_proof;
@@ -17,13 +16,13 @@ pub(crate) use mint_proof::MintRevealedValues;
 pub(crate) use proof::Proof;
 pub(crate) use spend_proof::SpendRevealedValues;
 
-use crate::types::DrkSecretKey;
+use keypair::SecretKey;
 
 #[derive(Clone)]
 pub struct OwnCoin {
     pub coin: coin::Coin,
     pub note: note::Note,
-    pub secret: DrkSecretKey,
+    pub secret: SecretKey,
     //pub witness: merkle::IncrementalWitness<merkle_node::MerkleNode>,
     //pub witness: BridgeFrontier<merkle::MerkleHash, 32>,
     pub nullifier: nullifier::Nullifier,

+ 13 - 14
src/crypto/note.rs

@@ -1,14 +1,13 @@
 use std::io;
 
 use crypto_api_chachapoly::ChachaPolyIetf;
-use pasta_curves::arithmetic::Field;
 use rand::rngs::OsRng;
 
-use super::{
-    diffie_hellman::{kdf_sapling, sapling_ka_agree},
-    util::mod_r_p,
-};
 use crate::{
+    crypto::{
+        diffie_hellman::{kdf_sapling, sapling_ka_agree},
+        keypair::{PublicKey, SecretKey},
+    },
     serial::{Decodable, Encodable, ReadExt, WriteExt},
     types::*,
     Error, Result,
@@ -56,11 +55,11 @@ impl Decodable for Note {
 }
 
 impl Note {
-    pub fn encrypt(&self, public: &DrkPublicKey) -> Result<EncryptedNote> {
-        let ephem_secret = DrkSecretKey::random(&mut OsRng);
-        let ephem_public = derive_public_key(ephem_secret);
-        let shared_secret = sapling_ka_agree(&mod_r_p(ephem_secret), public);
-        let key = kdf_sapling(shared_secret, &ephem_public);
+    pub fn encrypt(&self, public: &PublicKey) -> Result<EncryptedNote> {
+        let ephem_secret = SecretKey::random(&mut OsRng);
+        let ephem_public = PublicKey::from_secret(ephem_secret);
+        let shared_secret = sapling_ka_agree(&ephem_secret, public);
+        let key = kdf_sapling(&shared_secret, &ephem_public);
 
         let mut input = Vec::new();
         self.encode(&mut input)?;
@@ -79,7 +78,7 @@ impl Note {
 
 pub struct EncryptedNote {
     ciphertext: [u8; ENC_CIPHERTEXT_SIZE],
-    ephem_public: DrkPublicKey,
+    ephem_public: PublicKey,
 }
 
 impl Encodable for EncryptedNote {
@@ -101,9 +100,9 @@ impl Decodable for EncryptedNote {
 }
 
 impl EncryptedNote {
-    pub fn decrypt(&self, secret: &DrkSecretKey) -> Result<Note> {
-        let shared_secret = sapling_ka_agree(&mod_r_p(*secret), &self.ephem_public);
-        let key = kdf_sapling(shared_secret, &self.ephem_public);
+    pub fn decrypt(&self, secret: &SecretKey) -> Result<Note> {
+        let shared_secret = sapling_ka_agree(&secret, &self.ephem_public);
+        let key = kdf_sapling(&shared_secret, &self.ephem_public);
 
         let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
         assert_eq!(

+ 3 - 2
src/crypto/nullifier.rs

@@ -7,6 +7,7 @@ use halo2_gadgets::primitives::{
 use pasta_curves::{arithmetic::FieldExt, pallas};
 
 use crate::{
+    crypto::keypair::SecretKey,
     serial::{Decodable, Encodable, ReadExt, WriteExt},
     Result,
 };
@@ -15,8 +16,8 @@ use crate::{
 pub struct Nullifier(pub(crate) pallas::Base);
 
 impl Nullifier {
-    pub fn new(secret: pallas::Base, serial: pallas::Base) -> Self {
-        let nullifier = [secret, serial];
+    pub fn new(secret: SecretKey, serial: pallas::Base) -> Self {
+        let nullifier = [secret.0, serial];
         let nullifier = poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
         Nullifier(nullifier)
     }

+ 0 - 69
src/crypto/pasta_serial.rs

@@ -1,69 +0,0 @@
-use std::io;
-
-use pasta_curves as pasta;
-use pasta_curves::{arithmetic::FieldExt, group::GroupEncoding};
-
-use crate::{
-    serial::{Decodable, Encodable, ReadExt, WriteExt},
-    Error, Result,
-};
-
-impl Encodable for pasta::Fp {
-    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        s.write_slice(&self.to_bytes()[..])?;
-        Ok(32)
-    }
-}
-
-impl Decodable for pasta::Fp {
-    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
-        let mut bytes = [0u8; 32];
-        d.read_slice(&mut bytes)?;
-        let result = Self::from_bytes(&bytes);
-        if result.is_some().into() {
-            Ok(result.unwrap())
-        } else {
-            Err(Error::BadOperationType)
-        }
-    }
-}
-
-impl Encodable for pasta::Fq {
-    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        s.write_slice(&self.to_bytes()[..])?;
-        Ok(32)
-    }
-}
-
-impl Decodable for pasta::Fq {
-    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
-        let mut bytes = [0u8; 32];
-        d.read_slice(&mut bytes)?;
-        let result = Self::from_bytes(&bytes);
-        if result.is_some().into() {
-            Ok(result.unwrap())
-        } else {
-            Err(Error::BadOperationType)
-        }
-    }
-}
-
-impl Encodable for pasta::Ep {
-    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        s.write_slice(&self.to_bytes()[..])?;
-        Ok(32)
-    }
-}
-
-impl Decodable for pasta::Ep {
-    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
-        let mut bytes = [0u8; 32];
-        d.read_slice(&mut bytes)?;
-        let result = Self::from_bytes(&bytes);
-        if result.is_some().into() {
-            Ok(result.unwrap())
-        } else {
-            Err(Error::BadOperationType)
-        }
-    }
-}

+ 39 - 61
src/crypto/schnorr.rs

@@ -4,50 +4,47 @@ use halo2_gadgets::ecc::FixedPoints;
 use pasta_curves::{arithmetic::Field, group::GroupEncoding, pallas};
 use rand::rngs::OsRng;
 
-use super::{
-    constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
-    util::hash_to_scalar,
-};
 use crate::{
-    error::Result,
+    crypto::{
+        constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
+        keypair::{PublicKey, SecretKey},
+        util::{hash_to_scalar, mod_r_p},
+    },
     serial::{Decodable, Encodable},
-    types::{DrkPublicKey, DrkValueBlind, DrkValueCommit},
+    Result,
 };
 
-#[derive(Clone)]
-pub struct SecretKey(pub pallas::Scalar);
+pub struct Signature {
+    commit: pallas::Point,
+    response: pallas::Scalar,
+}
 
-impl SecretKey {
-    pub fn random() -> Self {
-        Self(pallas::Scalar::random(&mut OsRng))
-    }
+pub trait SchnorrSecret {
+    fn sign(&self, message: &[u8]) -> Signature;
+}
+
+pub trait SchnorrPublic {
+    fn verify(&self, message: &[u8], signature: &Signature) -> bool;
+}
 
-    pub fn sign(&self, message: &[u8]) -> Signature {
-        let mask = DrkValueBlind::random(&mut OsRng);
-        let commit = OrchardFixedBases::SpendAuthG.generator() * mask;
+impl SchnorrSecret for SecretKey {
+    fn sign(&self, message: &[u8]) -> Signature {
+        let mask = pallas::Scalar::random(&mut OsRng);
+        let commit = OrchardFixedBases::NullifierK.generator() * mask;
 
         let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
-        let response = mask + challenge * self.0;
+        let response = mask + challenge * mod_r_p(self.0);
 
         Signature { commit, response }
     }
-
-    pub fn public_key(&self) -> PublicKey {
-        let public_key = OrchardFixedBases::SpendAuthG.generator() * self.0;
-        PublicKey(public_key)
-    }
-
-    pub fn inner(&self) -> pallas::Scalar {
-        self.0
-    }
 }
 
-#[derive(PartialEq)]
-pub struct PublicKey(pub DrkPublicKey);
-
-pub struct Signature {
-    commit: DrkValueCommit,
-    response: DrkValueBlind,
+impl SchnorrPublic for PublicKey {
+    fn verify(&self, message: &[u8], signature: &Signature) -> bool {
+        let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
+        OrchardFixedBases::NullifierK.generator() * signature.response - self.0 * challenge ==
+            signature.commit
+    }
 }
 
 impl Encodable for Signature {
@@ -65,35 +62,16 @@ impl Decodable for Signature {
     }
 }
 
-impl PublicKey {
-    pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
-        let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
-        OrchardFixedBases::SpendAuthG.generator() * signature.response - self.0 * challenge ==
-            signature.commit
-    }
-
-    pub fn inner(&self) -> pallas::Point {
-        self.0
-    }
-}
-
-impl Encodable for PublicKey {
-    fn encode<S: io::Write>(&self, s: S) -> Result<usize> {
-        self.0.encode(s)
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_schnorr() {
+        let secret = SecretKey::random();
+        let message = b"Foo bar";
+        let signature = secret.sign(&message[..]);
+        let public = PublicKey::from_secret(secret);
+        assert!(public.verify(&message[..], &signature));
     }
 }
-
-impl Decodable for PublicKey {
-    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
-        Ok(Self(Decodable::decode(&mut d)?))
-    }
-}
-
-#[test]
-fn test_schnorr() {
-    let secret = SecretKey::random();
-    let message = b"Foo bar";
-    let signature = secret.sign(&message[..]);
-    let public = secret.public_key();
-    assert!(public.verify(&message[..], &signature));
-}

+ 19 - 21
src/crypto/spend_proof.rs

@@ -19,7 +19,10 @@ use super::{
 };
 use crate::{
     circuit::spend_contract::SpendContract,
-    crypto::{merkle_node::MerkleNode, schnorr},
+    crypto::{
+        keypair::{PublicKey, SecretKey},
+        merkle_node::MerkleNode,
+    },
     serial::{Decodable, Encodable},
     types::*,
     Result,
@@ -47,7 +50,7 @@ pub struct SpendRevealedValues {
     pub token_commit: DrkValueCommit,
     pub nullifier: Nullifier,
     pub merkle_root: MerkleNode,
-    pub signature_public: schnorr::PublicKey,
+    pub signature_public: PublicKey,
 }
 
 impl SpendRevealedValues {
@@ -59,27 +62,22 @@ impl SpendRevealedValues {
         token_blind: DrkValueBlind,
         serial: DrkSerial,
         coin_blind: DrkCoinBlind,
-        secret: DrkSecretKey,
+        secret: SecretKey,
         leaf_position: incrementalmerkletree::Position,
         merkle_path: Vec<MerkleNode>,
-        signature_secret: schnorr::SecretKey,
+        signature_secret: SecretKey,
     ) -> Self {
-        let nullifier = [secret, serial];
+        let nullifier = [secret.0, serial];
         let nullifier =
             primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
 
-        let public_key = derive_public_key(secret);
-        let coords = public_key.to_affine().coordinates().unwrap();
-        let messages = [
-            [*coords.x(), *coords.y()],
-            [DrkValue::from_u64(value), token_id],
-            [serial, coin_blind],
-        ];
-
-        let mut coin = DrkCoin::zero();
-        for msg in messages.iter() {
-            coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
-        }
+        let public_key = PublicKey::from_secret(secret);
+        let coords = public_key.0.to_affine().coordinates().unwrap();
+
+        let messages =
+            [*coords.x(), *coords.y(), DrkValue::from_u64(value), token_id, serial, coin_blind];
+
+        let coin = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages);
 
         let merkle_root = {
             let position: u64 = leaf_position.into();
@@ -103,7 +101,7 @@ impl SpendRevealedValues {
             token_commit,
             nullifier: Nullifier(nullifier),
             merkle_root,
-            signature_public: signature_secret.public_key(),
+            signature_public: PublicKey::from_secret(signature_secret),
         }
     }
 
@@ -160,10 +158,10 @@ pub fn create_spend_proof(
     token_blind: DrkValueBlind,
     serial: DrkSerial,
     coin_blind: DrkCoinBlind,
-    secret: DrkSecretKey,
+    secret: SecretKey,
     leaf_position: incrementalmerkletree::Position,
     merkle_path: Vec<MerkleNode>,
-    signature_secret: schnorr::SecretKey,
+    signature_secret: SecretKey,
 ) -> Result<(Proof, SpendRevealedValues)> {
     const K: u32 = 11;
 
@@ -184,7 +182,7 @@ pub fn create_spend_proof(
     let leaf_position: u64 = leaf_position.into();
 
     let c = SpendContract {
-        secret_key: Some(secret),
+        secret_key: Some(secret.0),
         serial: Some(serial),
         value: Some(DrkValue::from_u64(value)),
         asset: Some(token_id),

+ 9 - 6
src/service/bridge.rs

@@ -6,7 +6,10 @@ use async_trait::async_trait;
 use futures::stream::{FuturesUnordered, StreamExt};
 use log::{debug, error};
 
-use crate::{types::*, util::NetworkName, wallet::cashierdb::TokenKey, Error, Result};
+use crate::{
+    crypto::keypair::PublicKey, types::*, util::NetworkName, wallet::cashierdb::TokenKey, Error,
+    Result,
+};
 
 pub struct BridgeRequests {
     pub network: NetworkName,
@@ -53,7 +56,7 @@ pub struct TokenSubscribtion {
 pub struct TokenNotification {
     pub network: NetworkName,
     pub token_id: DrkTokenId,
-    pub drk_pub_key: DrkPublicKey,
+    pub drk_pub_key: PublicKey,
     pub received_balance: u64,
     pub decimals: u16,
 }
@@ -109,7 +112,7 @@ impl Bridge {
 
     pub async fn subscribe(
         self: Arc<Self>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> BridgeSubscribtion {
@@ -128,7 +131,7 @@ impl Bridge {
         self: Arc<Self>,
         req: async_channel::Receiver<BridgeRequests>,
         rep: async_channel::Sender<BridgeResponse>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<()> {
@@ -232,7 +235,7 @@ impl Bridge {
 pub trait NetworkClient {
     async fn subscribe(
         self: Arc<Self>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<TokenSubscribtion>;
@@ -242,7 +245,7 @@ pub trait NetworkClient {
         self: Arc<Self>,
         private_key: Vec<u8>,
         public_key: Vec<u8>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<String>;

+ 3 - 1
src/service/btc.rs

@@ -1,3 +1,5 @@
+// TODO: This module needs cleanup related to PublicKey/SecretKey types.
+
 use std::{
     cmp::max,
     collections::BTreeMap,
@@ -40,8 +42,8 @@ use secp256k1::{
 
 use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
 use crate::{
+    crypto::keypair::PublicKey as DrkPublicKey,
     serial::{deserialize, serialize, Decodable, Encodable},
-    types::*,
     util::{generate_id, NetworkName},
     Error, Result,
 };

+ 4 - 4
src/service/eth.rs

@@ -13,9 +13,9 @@ use serde_json::{json, Value};
 
 use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
 use crate::{
+    crypto::keypair::PublicKey,
     rpc::{jsonrpc, jsonrpc::JsonResult},
     serial::{deserialize, serialize, Decodable, Encodable},
-    types::*,
     util::{generate_id, parse::truncate, NetworkName},
     Error, Result,
 };
@@ -228,7 +228,7 @@ impl EthClient {
     async fn handle_subscribe_request(
         self: Arc<Self>,
         addr: String,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
     ) -> Result<()> {
         if self.subscriptions.lock().await.contains(&addr) {
             return Ok(())
@@ -381,7 +381,7 @@ impl EthClient {
 impl NetworkClient for EthClient {
     async fn subscribe(
         self: Arc<Self>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         _mint_address: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<TokenSubscribtion> {
@@ -414,7 +414,7 @@ impl NetworkClient for EthClient {
         self: Arc<Self>,
         _private_key: Vec<u8>,
         public_key: Vec<u8>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         _mint_address: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<String> {

+ 4 - 4
src/service/sol.rs

@@ -23,9 +23,9 @@ use tungstenite::Message;
 
 use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
 use crate::{
+    crypto::keypair::PublicKey,
     rpc::{jsonrpc, jsonrpc::JsonResult, websockets, websockets::WsStream},
     serial::{deserialize, serialize, Decodable, Encodable},
-    types::*,
     util::{generate_id, parse::truncate, NetworkName},
     Error, Result,
 };
@@ -85,7 +85,7 @@ impl SolClient {
     async fn handle_subscribe_request(
         self: Arc<Self>,
         keypair: Keypair,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint: Option<Pubkey>,
     ) -> SolResult<()> {
         debug!(target: "SOL BRIDGE", "handle_subscribe_request()");
@@ -396,7 +396,7 @@ impl SolClient {
 impl NetworkClient for SolClient {
     async fn subscribe(
         self: Arc<Self>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint_address: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<TokenSubscribtion> {
@@ -431,7 +431,7 @@ impl NetworkClient for SolClient {
         self: Arc<Self>,
         private_key: Vec<u8>,
         _public_key: Vec<u8>,
-        drk_pub_key: DrkPublicKey,
+        drk_pub_key: PublicKey,
         mint_address: Option<String>,
         executor: Arc<Executor<'_>>,
     ) -> Result<String> {

+ 17 - 20
src/state.rs

@@ -1,28 +1,25 @@
-use halo2_gadgets::ecc::FixedPoints;
 use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
 use log::debug;
-use pasta_curves::pallas;
 
 use crate::{
     blockchain::{rocks::columns, RocksColumn},
     crypto::{
         coin::Coin,
-        constants::OrchardFixedBases,
+        keypair::{PublicKey, SecretKey},
         merkle_node::MerkleNode,
         note::{EncryptedNote, Note},
         nullifier::Nullifier,
         proof::VerifyingKey,
-        schnorr,
-        util::mod_r_p,
         OwnCoin,
     },
+    serial::serialize,
     tx::Transaction,
-    wallet::WalletPtr,
+    wallet::walletdb::WalletPtr,
     Result,
 };
 
 pub trait ProgramState {
-    fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool;
+    fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool;
     fn is_valid_merkle(&self, merkle: &MerkleNode) -> bool;
     fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
     fn mint_vk(&self) -> &VerifyingKey;
@@ -61,15 +58,17 @@ pub enum VerifyFailed {
 
 pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyResult<StateUpdate> {
     // Check deposits are legit
-
     debug!(target: "STATE TRANSITION", "iterate clear_inputs");
 
     for (i, input) in tx.clear_inputs.iter().enumerate() {
         // Check the public key in the clear inputs
         // It should be a valid public key for the cashier
-
         if !state.is_valid_cashier_public_key(&input.signature_public) {
-            log::error!(target: "STATE TRANSITION", "Not valid cashier public key");
+            debug!(
+                "CASHIER PUBLIC: {}",
+                bs58::encode(serialize(&input.signature_public)).into_string()
+            );
+            log::error!(target: "STATE TRANSITION", "Invalid cashier public key");
             return Err(VerifyFailed::InvalidCashierKey(i))
         }
     }
@@ -108,7 +107,7 @@ pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyRe
     let mut enc_notes = vec![];
     for output in tx.outputs {
         // Gather all the coins
-        coins.push(Coin(output.revealed.coin));
+        coins.push(output.revealed.coin);
         enc_notes.push(output.enc_note);
     }
 
@@ -124,7 +123,7 @@ pub struct State {
     /// Nullifiers prevent double-spending
     pub nullifiers: RocksColumn<columns::Nullifiers>,
     /// List of Cashier public keys
-    pub public_keys: Vec<pallas::Point>,
+    pub public_keys: Vec<PublicKey>,
     /// Verifying key for the Mint contract
     pub mint_vk: VerifyingKey,
     /// Verifying key for the Spend contract
@@ -135,8 +134,8 @@ impl State {
     pub async fn apply(
         &mut self,
         update: StateUpdate,
-        secret_keys: Vec<pallas::Base>,
-        notify: Option<async_channel::Sender<(pallas::Point, u64)>>,
+        secret_keys: Vec<SecretKey>,
+        notify: Option<async_channel::Sender<(PublicKey, u64)>>,
         wallet: WalletPtr,
     ) -> Result<()> {
         // Extend our list of nullifiers with the ones from the update.
@@ -170,8 +169,7 @@ impl State {
 
                     wallet.put_own_coins(own_coin).await?;
 
-                    // TODO: Place somewhere proper
-                    let pubkey = OrchardFixedBases::NullifierK.generator() * mod_r_p(*secret);
+                    let pubkey = PublicKey::from_secret(*secret);
 
                     debug!("Received a coin: amount {}", note.value);
                     debug!("Send a notification");
@@ -186,7 +184,7 @@ impl State {
         Ok(())
     }
 
-    fn try_decrypt_note(ciphertext: &EncryptedNote, secret: pallas::Base) -> Option<Note> {
+    fn try_decrypt_note(ciphertext: &EncryptedNote, secret: SecretKey) -> Option<Note> {
         match ciphertext.decrypt(&secret) {
             Ok(note) => Some(note),
             Err(_) => None,
@@ -195,10 +193,9 @@ impl State {
 }
 
 impl ProgramState for State {
-    // TODO: Proper keypair type
-    fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool {
+    fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
         debug!("Check if it is a valid cashier public key");
-        self.public_keys.contains(&public.inner())
+        self.public_keys.contains(&public)
     }
 
     fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {

+ 12 - 7
src/tx/builder.rs

@@ -7,11 +7,15 @@ use super::{
 };
 use crate::{
     crypto::{
-        merkle_node::MerkleNode, mint_proof::create_mint_proof, note::Note, schnorr,
+        keypair::{PublicKey, SecretKey},
+        merkle_node::MerkleNode,
+        mint_proof::create_mint_proof,
+        note::Note,
+        schnorr::SchnorrSecret,
         spend_proof::create_spend_proof,
     },
     serial::Encodable,
-    types::{DrkCoinBlind, DrkPublicKey, DrkSecretKey, DrkSerial, DrkTokenId, DrkValueBlind},
+    types::{DrkCoinBlind, DrkSerial, DrkTokenId, DrkValueBlind},
     Result,
 };
 
@@ -24,20 +28,20 @@ pub struct TransactionBuilder {
 pub struct TransactionBuilderClearInputInfo {
     pub value: u64,
     pub token_id: DrkTokenId,
-    pub signature_secret: schnorr::SecretKey,
+    pub signature_secret: SecretKey,
 }
 
 pub struct TransactionBuilderInputInfo {
     pub leaf_position: incrementalmerkletree::Position,
     pub merkle_path: Vec<MerkleNode>,
-    pub secret: DrkSecretKey,
+    pub secret: SecretKey,
     pub note: Note,
 }
 
 pub struct TransactionBuilderOutputInfo {
     pub value: u64,
     pub token_id: DrkTokenId,
-    pub public: DrkPublicKey,
+    pub public: PublicKey,
 }
 
 impl TransactionBuilder {
@@ -63,11 +67,12 @@ impl TransactionBuilder {
         total
     }
 
+    // TODO: pass proving keys as args to this function
     pub fn build(self) -> Result<Transaction> {
         let mut clear_inputs = vec![];
         let token_blind = DrkValueBlind::random(&mut OsRng);
         for input in &self.clear_inputs {
-            let signature_public = input.signature_secret.public_key();
+            let signature_public = PublicKey::from_secret(input.signature_secret);
             let value_blind = DrkValueBlind::random(&mut OsRng);
 
             let clear_input = PartialTransactionClearInput {
@@ -86,7 +91,7 @@ impl TransactionBuilder {
         for input in self.inputs {
             input_blinds.push(input.note.value_blind);
 
-            let signature_secret = schnorr::SecretKey::random();
+            let signature_secret = SecretKey::random(&mut OsRng);
 
             let (proof, revealed) = create_spend_proof(
                 input.note.value,

+ 3 - 1
src/tx/mod.rs

@@ -7,10 +7,12 @@ use pasta_curves::group::Group;
 
 use crate::{
     crypto::{
+        keypair::PublicKey,
         mint_proof::verify_mint_proof,
         note::EncryptedNote,
         proof::{Proof, VerifyingKey},
         schnorr,
+        schnorr::SchnorrPublic,
         spend_proof::verify_spend_proof,
         util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
         MintRevealedValues, SpendRevealedValues,
@@ -38,7 +40,7 @@ pub struct TransactionClearInput {
     pub token_id: DrkTokenId,
     pub value_blind: DrkValueBlind,
     pub token_blind: DrkValueBlind,
-    pub signature_public: schnorr::PublicKey,
+    pub signature_public: PublicKey,
     pub signature: schnorr::Signature,
 }
 

+ 2 - 2
src/tx/partial.rs

@@ -2,7 +2,7 @@ use std::io;
 
 use super::TransactionOutput;
 use crate::{
-    crypto::{schnorr, spend_proof::SpendRevealedValues, Proof},
+    crypto::{keypair::PublicKey, spend_proof::SpendRevealedValues, Proof},
     error::Result,
     impl_vec,
     serial::{Decodable, Encodable, VarInt},
@@ -20,7 +20,7 @@ pub struct PartialTransactionClearInput {
     pub token_id: DrkTokenId,
     pub value_blind: DrkValueBlind,
     pub token_blind: DrkValueBlind,
-    pub signature_public: schnorr::PublicKey,
+    pub signature_public: PublicKey,
 }
 
 pub struct PartialTransactionInput {

+ 7 - 7
src/util/address.rs

@@ -1,21 +1,21 @@
-use crate::types::*;
-use group::GroupEncoding;
 use sha2::Digest;
 
+use crate::crypto::keypair::PublicKey;
+
 #[derive(Clone, Debug)]
 pub struct Address {
-    pub raw: DrkPublicKey,
+    pub raw: PublicKey,
     pub pkh: String,
 }
 
 impl Address {
-    pub fn new(raw: DrkPublicKey) -> Self {
+    pub fn new(raw: PublicKey) -> Self {
         let pkh = Self::pkh_address(&raw);
 
         Address { raw, pkh }
     }
 
-    fn get_hash(raw: &DrkPublicKey) -> Vec<u8> {
+    fn get_hash(raw: &PublicKey) -> Vec<u8> {
         // sha256
         let mut hasher = sha2::Sha256::new();
         hasher.update(raw.to_bytes());
@@ -28,7 +28,7 @@ impl Address {
         hash.to_vec()
     }
 
-    pub fn pkh_address(raw: &DrkPublicKey) -> String {
+    pub fn pkh_address(raw: &PublicKey) -> String {
         let mut hash = Self::get_hash(raw);
 
         // add version
@@ -44,7 +44,7 @@ impl Address {
 
         payload.append(&mut payload_hash[0..4].to_vec());
 
-        // base56 encoding
+        // base58 encoding
         let address: String = bs58::encode(payload).into_string();
 
         address

+ 8 - 8
src/util/token_list.rs

@@ -1,9 +1,9 @@
 use std::collections::HashMap;
 
-use pasta_curves::pallas;
 use serde_json::Value;
 
 use crate::{
+    types::DrkTokenId,
     util::{generate_id, NetworkName},
     Error, Result,
 };
@@ -55,7 +55,7 @@ impl TokenList {
 
 #[derive(Debug, Clone)]
 pub struct DrkTokenList {
-    pub tokens: HashMap<NetworkName, HashMap<String, pallas::Base>>,
+    pub tokens: HashMap<NetworkName, HashMap<String, DrkTokenId>>,
 }
 
 impl DrkTokenList {
@@ -64,28 +64,28 @@ impl DrkTokenList {
         let eth_symbols = eth_list.get_symbols()?;
         let btc_symbols = btc_list.get_symbols()?;
 
-        let sol_tokens: HashMap<String, pallas::Base> = sol_symbols
+        let sol_tokens: HashMap<String, DrkTokenId> = sol_symbols
             .iter()
             .filter_map(|symbol| {
                 Self::generate_hash_pair(sol_list, &NetworkName::Solana, symbol).ok()
             })
             .collect();
 
-        let eth_tokens: HashMap<String, pallas::Base> = eth_symbols
+        let eth_tokens: HashMap<String, DrkTokenId> = eth_symbols
             .iter()
             .filter_map(|symbol| {
                 Self::generate_hash_pair(eth_list, &NetworkName::Ethereum, symbol).ok()
             })
             .collect();
 
-        let btc_tokens: HashMap<String, pallas::Base> = btc_symbols
+        let btc_tokens: HashMap<String, DrkTokenId> = btc_symbols
             .iter()
             .filter_map(|symbol| {
                 Self::generate_hash_pair(btc_list, &NetworkName::Bitcoin, symbol).ok()
             })
             .collect();
 
-        let tokens: HashMap<NetworkName, HashMap<String, pallas::Base>> = HashMap::from([
+        let tokens: HashMap<NetworkName, HashMap<String, DrkTokenId>> = HashMap::from([
             (NetworkName::Solana, sol_tokens),
             (NetworkName::Ethereum, eth_tokens),
             (NetworkName::Bitcoin, btc_tokens),
@@ -98,7 +98,7 @@ impl DrkTokenList {
         token_list: &TokenList,
         network_name: &NetworkName,
         symbol: &str,
-    ) -> Result<(String, pallas::Base)> {
+    ) -> Result<(String, DrkTokenId)> {
         if let Some(token_id) = &token_list.search_id(symbol)? {
             return Ok((symbol.to_string(), generate_id(token_id, network_name)?))
         };
@@ -106,7 +106,7 @@ impl DrkTokenList {
         Err(Error::NotSupportedToken)
     }
 
-    pub fn symbol_from_id(&self, id: &pallas::Base) -> Result<Option<(NetworkName, String)>> {
+    pub fn symbol_from_id(&self, id: &DrkTokenId) -> Result<Option<(NetworkName, String)>> {
         for (network, tokens) in self.tokens.iter() {
             for (key, val) in tokens.iter() {
                 if val == id {

+ 21 - 12
src/wallet/cashierdb.rs

@@ -2,14 +2,19 @@ use std::{path::Path, str::FromStr};
 
 use async_std::sync::Arc;
 use log::{debug, error, info};
-use pasta_curves::pallas;
 use sqlx::{
     sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
     Row, SqlitePool,
 };
 
-use super::{Keypair, WalletApi};
-use crate::{client::ClientFailed, types::*, util::NetworkName, Error, Result};
+use super::wallet_api::WalletApi;
+use crate::{
+    client::ClientFailed,
+    crypto::keypair::{Keypair, PublicKey, SecretKey},
+    types::DrkTokenId,
+    util::NetworkName,
+    Error, Result,
+};
 
 pub type CashierDbPtr = Arc<CashierDb>;
 
@@ -27,7 +32,7 @@ pub struct WithdrawToken {
 }
 
 pub struct DepositToken {
-    pub drk_public_key: DrkPublicKey,
+    pub drk_public_key: PublicKey,
     pub token_key: TokenKey,
     pub token_id: DrkTokenId,
     pub mint_address: String,
@@ -64,11 +69,15 @@ impl CashierDb {
         let main_kps = include_str!("../../sql/cashier_main_keypairs.sql");
         let deposit_kps = include_str!("../../sql/cashier_deposit_keypairs.sql");
         let withdraw_kps = include_str!("../../sql/cashier_withdraw_keypairs.sql");
+
         let mut conn = self.conn.acquire().await?;
+
         debug!("Initializing main keypairs table");
         sqlx::query(main_kps).execute(&mut conn).await?;
+
         debug!("Initializing deposit keypairs table");
         sqlx::query(deposit_kps).execute(&mut conn).await?;
+
         debug!("Initializing withdraw keypairs table");
         sqlx::query(withdraw_kps).execute(&mut conn).await?;
         Ok(())
@@ -130,8 +139,8 @@ impl CashierDb {
     pub async fn put_withdraw_keys(
         &self,
         token_key_public: &[u8],
-        d_key_public: &pallas::Point,
-        d_key_secret: &pallas::Scalar,
+        d_key_public: &PublicKey,
+        d_key_secret: &SecretKey,
         network: &NetworkName,
         token_id: &DrkTokenId,
         mint_address: String,
@@ -167,7 +176,7 @@ impl CashierDb {
 
     pub async fn put_deposit_keys(
         &self,
-        d_key_public: &DrkPublicKey,
+        d_key_public: &PublicKey,
         token_key_secret: &[u8],
         token_key_public: &[u8],
         network: &NetworkName,
@@ -202,7 +211,7 @@ impl CashierDb {
         Ok(())
     }
 
-    pub async fn get_withdraw_private_keys(&self) -> Result<Vec<DrkSecretKey>> {
+    pub async fn get_withdraw_private_keys(&self) -> Result<Vec<SecretKey>> {
         debug!("Getting withdraw private keys");
         let confirm = self.get_value_serialized(&false)?;
 
@@ -217,7 +226,7 @@ impl CashierDb {
 
         let mut secret_keys = vec![];
         for row in rows {
-            let key = self.get_value_deserialized(row.get("d_key_secret"))?;
+            let key: SecretKey = self.get_value_deserialized(row.get("d_key_secret"))?;
             secret_keys.push(key);
         }
 
@@ -226,7 +235,7 @@ impl CashierDb {
 
     pub async fn get_withdraw_token_public_key_by_dkey_public(
         &self,
-        pubkey: &DrkPublicKey,
+        pubkey: &PublicKey,
     ) -> Result<Option<WithdrawToken>> {
         debug!("Get token address by pubkey");
         let d_key_public = self.get_value_serialized(pubkey)?;
@@ -259,7 +268,7 @@ impl CashierDb {
 
     pub async fn get_deposit_token_keys_by_dkey_public(
         &self,
-        d_key_public: &DrkPublicKey,
+        d_key_public: &PublicKey,
         network: &NetworkName,
     ) -> Result<Vec<TokenKey>> {
         debug!("Checking for existing dkey");
@@ -350,7 +359,7 @@ impl CashierDb {
 
     pub async fn confirm_deposit_key_record(
         &self,
-        d_key_public: &DrkPublicKey,
+        d_key_public: &PublicKey,
         network: &NetworkName,
     ) -> Result<()> {
         debug!("Confirm deposit keys");

+ 0 - 4
src/wallet/mod.rs

@@ -1,7 +1,3 @@
 pub mod cashierdb;
 pub mod wallet_api;
 pub mod walletdb;
-
-pub use cashierdb::{CashierDb, CashierDbPtr};
-pub use wallet_api::WalletApi;
-pub use walletdb::{Keypair, WalletDb, WalletPtr};

+ 21 - 24
src/wallet/walletdb.rs

@@ -1,10 +1,7 @@
 use std::{path::Path, str::FromStr};
 
 use async_std::sync::Arc;
-use halo2::arithmetic::Field;
-use halo2_gadgets::ecc::FixedPoints;
 use log::{debug, error, info};
-use pasta_curves::pallas;
 use rand::rngs::OsRng;
 use sqlx::{
     sqlite::{SqliteConnectOptions, SqliteJournalMode},
@@ -14,25 +11,23 @@ use sqlx::{
 use crate::{
     client::ClientFailed,
     crypto::{
-        coin::Coin, constants::OrchardFixedBases, note::Note, nullifier::Nullifier, util::mod_r_p,
+        coin::Coin,
+        keypair::{Keypair, PublicKey, SecretKey},
+        note::Note,
+        nullifier::Nullifier,
         OwnCoin, OwnCoins,
     },
     serial::serialize,
-    wallet::WalletApi,
+    types::DrkTokenId,
+    wallet::wallet_api::WalletApi,
     Error, Result,
 };
 
 pub type WalletPtr = Arc<WalletDb>;
 
-#[derive(Clone, Debug)]
-pub struct Keypair {
-    pub public: pallas::Point,
-    pub secret: pallas::Base,
-}
-
 #[derive(Clone, Debug)]
 pub struct Balance {
-    pub token_id: pallas::Base,
+    pub token_id: DrkTokenId,
     pub value: u64,
     pub nullifier: Nullifier,
 }
@@ -73,9 +68,12 @@ impl WalletDb {
         debug!("Initializing wallet database");
         let keys = include_str!("../../sql/keys.sql");
         let coins = include_str!("../../sql/coins.sql");
+
         let mut conn = self.conn.acquire().await?;
+
         debug!("Initializing keys table");
         sqlx::query(keys).execute(&mut conn).await?;
+
         debug!("Initializing coins table");
         sqlx::query(coins).execute(&mut conn).await?;
         Ok(())
@@ -92,23 +90,22 @@ impl WalletDb {
                 Err(Error::from(ClientFailed::KeyExists))
             }
             Err(_) => {
-                let secret = pallas::Base::random(&mut OsRng);
-                let public = OrchardFixedBases::NullifierK.generator() * mod_r_p(secret);
-                self.put_keypair(&public, &secret).await?;
+                let keypair = Keypair::random(&mut OsRng);
+                self.put_keypair(&keypair.public, &keypair.secret).await?;
                 Ok(())
             }
         }
     }
 
-    pub async fn put_keypair(&self, public: &pallas::Point, secret: &pallas::Base) -> Result<()> {
+    pub async fn put_keypair(&self, public: &PublicKey, secret: &SecretKey) -> Result<()> {
         debug!("Writing keypair into the wallet database");
-        let p = serialize(public);
-        let s = serialize(secret);
+        let pubkey = serialize(&public.0);
+        let secret = serialize(&secret.0);
 
         let mut conn = self.conn.acquire().await?;
         sqlx::query("INSERT INTO keys(public, secret) VALUES (?1, ?2)")
-            .bind(p)
-            .bind(s)
+            .bind(pubkey)
+            .bind(secret)
             .execute(&mut conn)
             .await?;
 
@@ -121,8 +118,8 @@ impl WalletDb {
 
         // TODO: Think about multiple keys
         let row = sqlx::query("SELECT * FROM keys").fetch_one(&mut conn).await?;
-        let public: pallas::Point = self.get_value_deserialized(row.get("public"))?;
-        let secret: pallas::Base = self.get_value_deserialized(row.get("secret"))?;
+        let public: PublicKey = self.get_value_deserialized(row.get("public"))?;
+        let secret: SecretKey = self.get_value_deserialized(row.get("secret"))?;
 
         Ok(vec![Keypair { public, secret }])
     }
@@ -256,7 +253,7 @@ impl WalletDb {
         Ok(Balances { list })
     }
 
-    pub async fn get_token_id(&self) -> Result<Vec<pallas::Base>> {
+    pub async fn get_token_id(&self) -> Result<Vec<DrkTokenId>> {
         debug!("Getting token ID");
         let is_spent = 0;
 
@@ -275,7 +272,7 @@ impl WalletDb {
         Ok(token_ids)
     }
 
-    pub async fn token_id_exists(&self, token_id: pallas::Base) -> Result<bool> {
+    pub async fn token_id_exists(&self, token_id: DrkTokenId) -> Result<bool> {
         debug!("Checking if token ID exists");
         let is_spent = 0;
         let id = self.get_value_serialized(&token_id)?;