|
|
@@ -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(¬e.serial)?;
|
|
|
let coin_blind = self.get_value_serialized(¬e.coin_blind)?;
|
|
|
let valcom_blind = self.get_value_serialized(¬e.valcom_blind)?;
|
|
|
- let value = self.get_value_serialized(¬e.value)?;
|
|
|
- let asset_id = self.get_value_serialized(¬e.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(())
|
|
|
+ //}
|
|
|
}
|