Kaynağa Gözat

fix bugs and add test cases inside walletdb.rs

ghassmo 5 yıl önce
ebeveyn
işleme
2d859c9cb1
1 değiştirilmiş dosya ile 208 ekleme ve 130 silme
  1. 208 130
      src/wallet/walletdb.rs

+ 208 - 130
src/wallet/walletdb.rs

@@ -60,8 +60,8 @@ impl WalletDb {
             conn.pragma_update(None, "key", &self.password)?;
             conn.execute_batch(&contents)?;
         } else {
-            println!("Password is empty. You must set a password to use the wallet.");
-            println!("Current password: {}", self.password);
+            info!("Password is empty. You must set a password to use the wallet.");
+            info!("Current password: {}", self.password);
             return Err(Error::EmptyPassword);
         }
         Ok(())
@@ -75,43 +75,54 @@ impl WalletDb {
         Ok(())
     }
 
-    fn parse_own_coin(
-        &self,
-        row: &rusqlite::Row,
-    ) -> Result<(Coin, Note, jubjub::Fr, IncrementalWitness<MerkleNode>)> {
-        let coin = self.get_value_deserialized(row.get(0)?)?;
-
-        // note
-        let serial = self.get_value_deserialized(row.get(1)?)?;
-        let coin_blind = self.get_value_deserialized(row.get(2)?)?;
-        let valcom_blind = self.get_value_deserialized(row.get(3)?)?;
-        let value = self.get_value_deserialized(row.get(4)?)?;
-        let asset_id = self.get_value_deserialized(row.get(5)?)?;
-
-        let note = Note {
-            serial,
-            value,
-            asset_id,
-            coin_blind,
-            valcom_blind,
-        };
-
-        let witness = self.get_value_deserialized(row.get(6)?)?;
-        let secret = self.get_value_deserialized(row.get(7)?)?;
-
-        Ok((coin, note, secret, witness))
-    }
-
     pub fn get_own_coins(&self) -> Result<OwnCoins> {
         // open connection
         let conn = Connection::open(&self.path)?;
         // unlock database
         conn.pragma_update(None, "key", &self.password)?;
-        // return key_id from key_private
+
         let mut coins = conn.prepare("SELECT * FROM coins")?;
         let rows = coins.query_map([], |row| {
-            self.parse_own_coin(row)
-                .map_err(|_| rusqlite::Error::InvalidQuery)
+            let coin = self.get_value_deserialized(row.get(1)?).unwrap();
+
+            // note
+            let serial = self.get_value_deserialized(row.get(2)?).unwrap();
+            let coin_blind = self.get_value_deserialized(row.get(3)?).unwrap();
+            let valcom_blind = self.get_value_deserialized(row.get(4)?).unwrap();
+            let value: u64 = row.get(5)?;
+            let asset_id: u64 = row.get(6)?;
+
+            let note = Note {
+                serial,
+                value,
+                asset_id,
+                coin_blind,
+                valcom_blind,
+            };
+
+            let witness = self.get_value_deserialized(row.get(7)?).unwrap();
+            let key_id: u64 = row.get(8)?;
+
+            // return key_private from key_id
+            let mut get_private_key =
+                conn.prepare("SELECT key_private FROM keys WHERE key_id = :key_id")?;
+
+            let rows = get_private_key.query_map(&[(":key_id", &key_id)], |row| row.get(0))?;
+
+            let mut secret = Vec::new();
+            for id in rows {
+                secret.push(id?)
+            }
+
+            let secret: jubjub::Fr = self
+                .get_value_deserialized(
+                    secret
+                        .pop()
+                        .expect("unable to load public_key from walletdb"),
+                )
+                .unwrap();
+
+            Ok((coin, note, secret, witness))
         })?;
 
         let mut own_coins = Vec::new();
@@ -134,8 +145,8 @@ impl WalletDb {
         let serial = self.get_value_serialized(&note.serial)?;
         let coin_blind = self.get_value_serialized(&note.coin_blind)?;
         let valcom_blind = self.get_value_serialized(&note.valcom_blind)?;
-        let value = self.get_value_serialized(&note.value)?;
-        let asset_id = self.get_value_serialized(&note.asset_id)?;
+        let value: u64 = note.value;
+        let asset_id: u64 = note.asset_id;
         let witness = self.get_value_serialized(&witness)?;
         let secret = self.get_value_serialized(&secret)?;
         // open connection
@@ -147,24 +158,25 @@ impl WalletDb {
         let mut get_id =
             conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
 
-        let rows = get_id.query_map::<u8, _, _>(&[(":key_private", &secret)], |row| row.get(0))?;
+        let rows = get_id.query_map::<u64, _, _>(&[(":key_private", &secret)], |row| row.get(0))?;
 
         let mut key_id = Vec::new();
         for id in rows {
             key_id.push(id?)
         }
+
         conn.execute(
             "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
             VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
             named_params! {
-            ":coin": coin,
-            ":serial": serial,
-            ":value": value,
-            ":asset_id": asset_id,
-            ":coin_blind": coin_blind,
-            ":valcom_blind": valcom_blind,
-            ":witness": witness,
-            ":key_id": key_id.pop().expect("key_id not found!"),
+                ":coin": coin,
+                ":serial": serial,
+                ":value": value,
+                ":asset_id": asset_id,
+                ":coin_blind": coin_blind,
+                ":valcom_blind": valcom_blind,
+                ":witness": witness,
+                ":key_id": key_id.pop().expect("key_id not found!"),
             },
         )?;
         Ok(())
@@ -190,7 +202,6 @@ impl WalletDb {
 
     pub fn put_keypair(&self, key_public: Vec<u8>, key_private: Vec<u8>) -> Result<()> {
         let conn = Connection::open(&self.path)?;
-        println!("{}", self.password);
         conn.pragma_update(None, "key", &self.password)?;
         conn.execute(
             "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
@@ -216,7 +227,7 @@ impl WalletDb {
         conn.pragma_update(None, "key", &self.password)?;
         let mut stmt = conn.prepare("SELECT key_public FROM keys")?;
         // this just gets the first key. maybe we should randomize this
-        let key_iter = stmt.query_map::<Vec<u8>, _, _>([], |row| row.get(0))?;
+        let key_iter = stmt.query_map([], |row| row.get(0))?;
         let mut pub_keys = Vec::new();
         for key in key_iter {
             pub_keys.push(key?);
@@ -235,12 +246,16 @@ impl WalletDb {
         let conn = Connection::open(&self.path)?;
         conn.pragma_update(None, "key", &self.password)?;
         let mut stmt = conn.prepare("SELECT key_public FROM cashier")?;
-        let key_iter = stmt.query_map::<u8, _, _>([], |row| row.get(0))?;
+        let key_iter = stmt.query_map([], |row| row.get(0))?;
         let mut pub_keys = Vec::new();
         for key in key_iter {
             pub_keys.push(key?);
         }
-        let public: jubjub::SubgroupPoint = self.get_value_deserialized(pub_keys)?;
+        let public: jubjub::SubgroupPoint = self.get_value_deserialized(
+            pub_keys
+                .pop()
+                .expect("unable to load cashier public_key from walletdb"),
+        )?;
         Ok(public)
     }
 
@@ -249,12 +264,15 @@ impl WalletDb {
         let conn = Connection::open(&self.path)?;
         conn.pragma_update(None, "key", &self.password)?;
         let mut stmt = conn.prepare("SELECT key_private FROM keys")?;
-        let key_iter = stmt.query_map::<u8, _, _>([], |row| row.get(0))?;
+        let key_iter = stmt.query_map([], |row| row.get(0))?;
         let mut keys = Vec::new();
         for key in key_iter {
             keys.push(key?);
         }
-        let private: jubjub::Fr = self.get_value_deserialized(keys)?;
+        let private: jubjub::Fr = self.get_value_deserialized(
+            keys.pop()
+                .expect("unable to load private key from walletdb"),
+        )?;
         Ok(private)
     }
 
@@ -283,101 +301,161 @@ mod tests {
     use super::*;
 
     #[test]
-    pub fn test_unlock() -> Result<()> {
-        let password = "roseiscool2021";
-        let path = join_config_path(&PathBuf::from("wallet.db"))?;
-        let contents = include_str!("../../res/schema.sql");
-        let conn = Connection::open(&path)?;
-        debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", path);
-        conn.pragma_update(None, "key", &password)?;
-        conn.execute_batch(&contents)?;
-        Ok(())
-    }
+    pub fn test_save_and_load_keypair() -> Result<()> {
+        let wallet = WalletDb::new("test_wallet.db", "darkfi".into())?;
+        wallet.init_db()?;
 
-    #[test]
-    pub fn test_keypair() -> Result<()> {
-        let path = join_config_path(&PathBuf::from("wallet.db"))?;
-        let conn = Connection::open(path)?;
         let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
         let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
         let key_public = serial::serialize(&public);
         let key_private = serial::serialize(&secret);
-        let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
-        let _rows = stmt.query([])?;
-        conn.execute(
-            "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
-            params![key_public, key_private],
-        )?;
+
+        wallet.put_keypair(key_public, key_private)?;
+
+        let public2 = wallet.get_public()?;
+        let secret2 = wallet.get_private()?;
+
+        assert_eq!(public, public2);
+        assert_eq!(secret, secret2);
+
         Ok(())
     }
 
+    // This test will fail
     #[test]
-    pub fn test_get_id() -> Result<()> {
-        let path = join_config_path(&PathBuf::from("wallet.db"))?;
-        let conn = Connection::open(path)?;
+    pub fn test_put_and_get_own_coins() -> Result<()> {
+        let wallet = WalletDb::new("test_wallet.db", "darkfi".into())?;
+        wallet.init_db()?;
+
         let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
-        let key_private = serial::serialize(&secret);
         let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
         let key_public = serial::serialize(&public);
-        let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
-        let _rows = stmt.query([])?;
-        conn.execute(
-            "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
-            params![key_public, key_private],
-        )?;
-        let mut get_id =
-            conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
-        let rows =
-            get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
-        let mut key_id = Vec::new();
-        for id in rows {
-            key_id.push(id?)
-        }
-        println!("FOUND ID: {:?}", key_id.pop().unwrap());
-        Ok(())
-    }
+        let key_private = serial::serialize(&secret);
 
-    #[test]
-    pub fn test_own_coins() -> Result<()> {
-        let key_private = Vec::new();
-        let coin = Vec::new();
-        let serial = Vec::new();
-        let coin_blind = Vec::new();
-        let valcom_blind = Vec::new();
-        let value = Vec::new();
-        let asset_id = Vec::new();
-        let witness = Vec::new();
-        let path = join_config_path(&PathBuf::from("wallet.db"))?;
-        let conn = Connection::open(path)?;
-        let contents = include_str!("../../res/schema.sql");
-        match conn.execute_batch(&contents) {
-            Ok(v) => println!("Database initalized successfully {:?}", v),
-            Err(err) => println!("Error: {}", err),
+        wallet.put_keypair(key_public, key_private)?;
+
+        let note = Note {
+            serial: jubjub::Fr::random(&mut OsRng),
+            value: 110,
+            asset_id: 1,
+            coin_blind: jubjub::Fr::random(&mut OsRng),
+            valcom_blind: jubjub::Fr::random(&mut OsRng),
         };
-        //let mut unlock = conn.prepare("PRAGMA key = 'testkey'")?;
-        //let _rows = unlock.query([])?;
-        let mut get_id =
-            conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
-        let rows =
-            get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
-        let mut key_id = Vec::new();
-        for id in rows {
-            key_id.push(id?)
-        }
-        conn.execute(
-            "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
-            VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
-            named_params! {
-            ":coin": coin,
-            ":serial": serial,
-            ":value": value,
-            ":asset_id": asset_id,
-            ":coin_blind": coin_blind,
-            ":valcom_blind": valcom_blind,
-            ":witness": witness,
-            ":key_id": key_id.pop().expect("key_id not found!"),
-            },
-        )?;
+
+        let tree = crate::crypto::merkle::CommitmentTree::empty();
+
+        let witness = IncrementalWitness::from_tree(&tree);
+
+        let coin = Coin::new([0; 32]);
+
+        wallet.put_own_coins(coin.clone(), note.clone(), witness, secret)?;
+
+        println!("put_own_coins done");
+
+        let own_coin = wallet.get_own_coins()?[0].clone();
+
+        println!("get_own_coins done");
+
+        assert_eq!(own_coin.2, secret);
+
         Ok(())
     }
+
+    //#[test]
+    //    let password = "roseiscool2021";
+    //    let path = join_config_path(&PathBuf::from("wallet.db"))?;
+    //    let contents = include_str!("../../res/schema.sql");
+    //    let conn = Connection::open(&path)?;
+    //    debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", path);
+    //    conn.pragma_update(None, "key", &password)?;
+    //    conn.execute_batch(&contents)?;
+    //    Ok(())
+    //}
+
+    //#[test]
+    //pub fn test_keypair() -> Result<()> {
+    //    let path = join_config_path(&PathBuf::from("wallet.db"))?;
+    //    let conn = Connection::open(path)?;
+    //    let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
+    //    let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
+    //    let key_public = serial::serialize(&public);
+    //    let key_private = serial::serialize(&secret);
+    //    let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
+    //    let _rows = stmt.query([])?;
+    //    conn.execute(
+    //        "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
+    //        params![key_public, key_private],
+    //    )?;
+    //    Ok(())
+    //}
+
+    //#[test]
+    //pub fn test_get_id() -> Result<()> {
+    //    let path = join_config_path(&PathBuf::from("wallet.db"))?;
+    //    let conn = Connection::open(path)?;
+    //    let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
+    //    let key_private = serial::serialize(&secret);
+    //    let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
+    //    let key_public = serial::serialize(&public);
+    //    let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
+    //    let _rows = stmt.query([])?;
+    //    conn.execute(
+    //        "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
+    //        params![key_public, key_private],
+    //    )?;
+    //    let mut get_id =
+    //        conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
+    //    let rows =
+    //        get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
+    //    let mut key_id = Vec::new();
+    //    for id in rows {
+    //        key_id.push(id?)
+    //    }
+    //    println!("FOUND ID: {:?}", key_id.pop().unwrap());
+    //    Ok(())
+    //}
+
+    //#[test]
+    //pub fn test_own_coins() -> Result<()> {
+    //    let key_private = Vec::new();
+    //    let coin = Vec::new();
+    //    let serial = Vec::new();
+    //    let coin_blind = Vec::new();
+    //    let valcom_blind = Vec::new();
+    //    let value = Vec::new();
+    //    let asset_id = Vec::new();
+    //    let witness = Vec::new();
+    //    let path = join_config_path(&PathBuf::from("wallet.db"))?;
+    //    let conn = Connection::open(path)?;
+    //    let contents = include_str!("../../res/schema.sql");
+    //    match conn.execute_batch(&contents) {
+    //        Ok(v) => println!("Database initalized successfully {:?}", v),
+    //        Err(err) => println!("Error: {}", err),
+    //    };
+    //    //let mut unlock = conn.prepare("PRAGMA key = 'testkey'")?;
+    //    //let _rows = unlock.query([])?;
+    //    let mut get_id =
+    //        conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
+    //    let rows =
+    //        get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
+    //    let mut key_id = Vec::new();
+    //    for id in rows {
+    //        key_id.push(id?)
+    //    }
+    //    conn.execute(
+    //        "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
+    //        VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
+    //        named_params! {
+    //            ":coin": coin,
+    //            ":serial": serial,
+    //            ":value": value,
+    //            ":asset_id": asset_id,
+    //            ":coin_blind": coin_blind,
+    //            ":valcom_blind": valcom_blind,
+    //            ":witness": witness,
+    //            ":key_id": key_id.pop().expect("key_id not found!"),
+    //        },
+    //    )?;
+    //    Ok(())
+    //}
 }