From 2f09d0e60467fb759b884ce8225e793d5a089f59 Mon Sep 17 00:00:00 2001 From: ngutech21 Date: Sat, 6 Apr 2024 17:15:04 +0200 Subject: [PATCH] feat: compile-time check queries in localstore fixes #228 --- ...8ff27f74e24d8c2ca37c10861c2e128905013.json | 12 +++ ...75208743b9fc168fa8cffd848b671014b8bf1.json | 38 ++++++++ ...d0a41bca0c9c0eece9ec91a50195412d9adae.json | 56 ++++++++++++ ...0945ae771fe2b59169958bdc9ce7c0eb73090.json | 12 +++ ...ebd53e8d588375b06e40335e91da39c680ad3.json | 20 +++++ ...3a04db5b9639ea87a8a1472ccca5d5194afc6.json | 12 +++ ...c38e1192ef3f25f9204550ed30aa3a0bd7e3f.json | 12 +++ moksha-wallet/Cargo.toml | 2 +- .../migrations/20230530061910_init.sql | 8 +- moksha-wallet/src/localstore/sqlite.rs | 86 ++++++++----------- 10 files changed, 204 insertions(+), 54 deletions(-) create mode 100644 moksha-wallet/.sqlx/query-0913842a79a647c1190faa24d948ff27f74e24d8c2ca37c10861c2e128905013.json create mode 100644 moksha-wallet/.sqlx/query-1aa7a37640cde629ef99ebb746875208743b9fc168fa8cffd848b671014b8bf1.json create mode 100644 moksha-wallet/.sqlx/query-609877b640a209756b504ef93f9d0a41bca0c9c0eece9ec91a50195412d9adae.json create mode 100644 moksha-wallet/.sqlx/query-6caae4e19877ee8ab21df304f5d0945ae771fe2b59169958bdc9ce7c0eb73090.json create mode 100644 moksha-wallet/.sqlx/query-7373a18c132ed16ac8ae383f008ebd53e8d588375b06e40335e91da39c680ad3.json create mode 100644 moksha-wallet/.sqlx/query-c08a68cb103a8fe16fddbe23d163a04db5b9639ea87a8a1472ccca5d5194afc6.json create mode 100644 moksha-wallet/.sqlx/query-e99d7276a6bb8d0b0f456e8d00ec38e1192ef3f25f9204550ed30aa3a0bd7e3f.json diff --git a/moksha-wallet/.sqlx/query-0913842a79a647c1190faa24d948ff27f74e24d8c2ca37c10861c2e128905013.json b/moksha-wallet/.sqlx/query-0913842a79a647c1190faa24d948ff27f74e24d8c2ca37c10861c2e128905013.json new file mode 100644 index 00000000..88526672 --- /dev/null +++ b/moksha-wallet/.sqlx/query-0913842a79a647c1190faa24d948ff27f74e24d8c2ca37c10861c2e128905013.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT INTO keysets (keyset_id, mint_url, currency_unit, last_index, public_keys, active) VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT(keyset_id, mint_url) DO UPDATE SET currency_unit = $3, public_keys = $5, active = $6;\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 6 + }, + "nullable": [] + }, + "hash": "0913842a79a647c1190faa24d948ff27f74e24d8c2ca37c10861c2e128905013" +} diff --git a/moksha-wallet/.sqlx/query-1aa7a37640cde629ef99ebb746875208743b9fc168fa8cffd848b671014b8bf1.json b/moksha-wallet/.sqlx/query-1aa7a37640cde629ef99ebb746875208743b9fc168fa8cffd848b671014b8bf1.json new file mode 100644 index 00000000..3811e9b7 --- /dev/null +++ b/moksha-wallet/.sqlx/query-1aa7a37640cde629ef99ebb746875208743b9fc168fa8cffd848b671014b8bf1.json @@ -0,0 +1,38 @@ +{ + "db_name": "SQLite", + "query": "SELECT keyset_id, amount, C, secret FROM proofs;", + "describe": { + "columns": [ + { + "name": "keyset_id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "amount", + "ordinal": 1, + "type_info": "Int64" + }, + { + "name": "C", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "secret", + "ordinal": 3, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "1aa7a37640cde629ef99ebb746875208743b9fc168fa8cffd848b671014b8bf1" +} diff --git a/moksha-wallet/.sqlx/query-609877b640a209756b504ef93f9d0a41bca0c9c0eece9ec91a50195412d9adae.json b/moksha-wallet/.sqlx/query-609877b640a209756b504ef93f9d0a41bca0c9c0eece9ec91a50195412d9adae.json new file mode 100644 index 00000000..a78fb2d9 --- /dev/null +++ b/moksha-wallet/.sqlx/query-609877b640a209756b504ef93f9d0a41bca0c9c0eece9ec91a50195412d9adae.json @@ -0,0 +1,56 @@ +{ + "db_name": "SQLite", + "query": "SELECT id, mint_url, keyset_id, currency_unit, active, last_index, public_keys FROM keysets;", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int64" + }, + { + "name": "mint_url", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "keyset_id", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "currency_unit", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "active", + "ordinal": 4, + "type_info": "Bool" + }, + { + "name": "last_index", + "ordinal": 5, + "type_info": "Int64" + }, + { + "name": "public_keys", + "ordinal": 6, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "609877b640a209756b504ef93f9d0a41bca0c9c0eece9ec91a50195412d9adae" +} diff --git a/moksha-wallet/.sqlx/query-6caae4e19877ee8ab21df304f5d0945ae771fe2b59169958bdc9ce7c0eb73090.json b/moksha-wallet/.sqlx/query-6caae4e19877ee8ab21df304f5d0945ae771fe2b59169958bdc9ce7c0eb73090.json new file mode 100644 index 00000000..592022c2 --- /dev/null +++ b/moksha-wallet/.sqlx/query-6caae4e19877ee8ab21df304f5d0945ae771fe2b59169958bdc9ce7c0eb73090.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT INTO proofs (keyset_id, amount, C, secret, time_created) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP);", + "describe": { + "columns": [], + "parameters": { + "Right": 4 + }, + "nullable": [] + }, + "hash": "6caae4e19877ee8ab21df304f5d0945ae771fe2b59169958bdc9ce7c0eb73090" +} diff --git a/moksha-wallet/.sqlx/query-7373a18c132ed16ac8ae383f008ebd53e8d588375b06e40335e91da39c680ad3.json b/moksha-wallet/.sqlx/query-7373a18c132ed16ac8ae383f008ebd53e8d588375b06e40335e91da39c680ad3.json new file mode 100644 index 00000000..e7f90b9c --- /dev/null +++ b/moksha-wallet/.sqlx/query-7373a18c132ed16ac8ae383f008ebd53e8d588375b06e40335e91da39c680ad3.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT seed_words FROM seed;", + "describe": { + "columns": [ + { + "name": "seed_words", + "ordinal": 0, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false + ] + }, + "hash": "7373a18c132ed16ac8ae383f008ebd53e8d588375b06e40335e91da39c680ad3" +} diff --git a/moksha-wallet/.sqlx/query-c08a68cb103a8fe16fddbe23d163a04db5b9639ea87a8a1472ccca5d5194afc6.json b/moksha-wallet/.sqlx/query-c08a68cb103a8fe16fddbe23d163a04db5b9639ea87a8a1472ccca5d5194afc6.json new file mode 100644 index 00000000..95f20786 --- /dev/null +++ b/moksha-wallet/.sqlx/query-c08a68cb103a8fe16fddbe23d163a04db5b9639ea87a8a1472ccca5d5194afc6.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "UPDATE keysets SET last_index = $1 WHERE id = $2;", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "c08a68cb103a8fe16fddbe23d163a04db5b9639ea87a8a1472ccca5d5194afc6" +} diff --git a/moksha-wallet/.sqlx/query-e99d7276a6bb8d0b0f456e8d00ec38e1192ef3f25f9204550ed30aa3a0bd7e3f.json b/moksha-wallet/.sqlx/query-e99d7276a6bb8d0b0f456e8d00ec38e1192ef3f25f9204550ed30aa3a0bd7e3f.json new file mode 100644 index 00000000..4cc4208d --- /dev/null +++ b/moksha-wallet/.sqlx/query-e99d7276a6bb8d0b0f456e8d00ec38e1192ef3f25f9204550ed30aa3a0bd7e3f.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT INTO seed (seed_words) VALUES ($1);", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "e99d7276a6bb8d0b0f456e8d00ec38e1192ef3f25f9204550ed30aa3a0bd7e3f" +} diff --git a/moksha-wallet/Cargo.toml b/moksha-wallet/Cargo.toml index 1a216224..5792c696 100644 --- a/moksha-wallet/Cargo.toml +++ b/moksha-wallet/Cargo.toml @@ -39,7 +39,7 @@ tokio = { version = "1.37.0", features = ["rt", "sync"] } [target.'cfg(not(target_family="wasm"))'.dependencies] reqwest = { version = "0.12.1", features = ["json", "rustls-tls"], default-features = false } tokio = { version = "1.37.0", features = ["rt", "rt-multi-thread", "macros"] } -sqlx = { version = "0.7.4", default-features = false, features = ["sqlite", "runtime-tokio", "tls-rustls", "migrate", "macros"] } +sqlx = { version = "0.7.4", default-features = false, features = ["sqlite", "runtime-tokio", "tls-rustls", "migrate", "macros", "json"] } [dev-dependencies] tempfile = "3.10.1" diff --git a/moksha-wallet/migrations/20230530061910_init.sql b/moksha-wallet/migrations/20230530061910_init.sql index 836fba1a..9d266486 100644 --- a/moksha-wallet/migrations/20230530061910_init.sql +++ b/moksha-wallet/migrations/20230530061910_init.sql @@ -1,6 +1,6 @@ -- Add migration script here CREATE TABLE IF NOT EXISTS proofs ( - keyset_id TEXT, + keyset_id TEXT NOT NULL, amount INTEGER NOT NULL, C TEXT NOT NULL, secret TEXT NOT NULL, @@ -13,8 +13,8 @@ CREATE TABLE IF NOT EXISTS keysets ( mint_url TEXT NOT NULL, keyset_id TEXT NOT NULL, currency_unit TEXT NOT NULL, - active BOOL DEFAULT TRUE, - last_index INTEGER, - public_keys JSON CHECK (json_valid(public_keys)), + active BOOL NOT NULL DEFAULT TRUE, + last_index INTEGER NOT NULL, + public_keys TEXT NOT NULL CHECK (json_valid(public_keys)), UNIQUE (keyset_id, mint_url) ); \ No newline at end of file diff --git a/moksha-wallet/src/localstore/sqlite.rs b/moksha-wallet/src/localstore/sqlite.rs index ae274f8b..217339f1 100644 --- a/moksha-wallet/src/localstore/sqlite.rs +++ b/moksha-wallet/src/localstore/sqlite.rs @@ -11,7 +11,6 @@ use crate::localstore::{LocalStore, WalletKeyset}; use sqlx::sqlite::SqliteError; -use sqlx::Row; #[derive(Clone, Debug)] pub struct SqliteLocalStore { @@ -40,6 +39,7 @@ impl LocalStore for SqliteLocalStore { let placeholders: Vec = (1..=proof_secrets.len()) .map(|i| format!("?{}", i)) .collect(); + let sql = format!( "DELETE FROM proofs WHERE secret IN ({})", placeholders.join(",") @@ -59,14 +59,11 @@ impl LocalStore for SqliteLocalStore { proofs: &Proofs, ) -> Result<(), MokshaWalletError> { for proof in proofs.proofs() { - sqlx::query( - r#"INSERT INTO proofs (keyset_id, amount, C, secret, time_created) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP); - "#, - ) - .bind(proof.keyset_id) - .bind(proof.amount as i64) - .bind(proof.c.to_string()) - .bind(proof.secret) + let c = proof.c.to_string(); + let amount = proof.amount as i64; + sqlx::query!( + "INSERT INTO proofs (keyset_id, amount, C, secret, time_created) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP);", + proof.keyset_id,amount, c, proof.secret ) .execute(&mut **tx) .await?; } @@ -77,27 +74,21 @@ impl LocalStore for SqliteLocalStore { &self, tx: &mut sqlx::Transaction, ) -> Result { - let rows = sqlx::query("SELECT * FROM proofs;") + let rows = sqlx::query!("SELECT keyset_id, amount, C, secret FROM proofs;") .fetch_all(&mut **tx) .await?; + // FIXME read time_created Ok(rows - .iter() - .map(|row| { - let id = row.get(0); - let amount: i64 = row.get(1); - let c: String = row.get(2); - let secret: String = row.get(3); - let _time_created: String = row.get(4); // TODO use time_created - Ok(Proof { - keyset_id: id, - amount: amount as u64, - c: c.parse().expect("Invalid Pubkey"), - secret, + .into_iter() + .map(|row| Proof{ + keyset_id: row.keyset_id, + amount: row.amount as u64, + c: row.C.parse().expect("Invalid Pubkey"), + secret: row.secret, script: None, - }) }) - .collect::, SqliteError>>()? + .collect::>() .into()) } @@ -106,16 +97,15 @@ impl LocalStore for SqliteLocalStore { tx: &mut sqlx::Transaction, keyset: &WalletKeyset, ) -> Result<(), MokshaWalletError> { - sqlx::query( + let keyset_id = keyset.keyset_id.to_string(); + let mint_url = keyset.mint_url.as_str(); + let currency_unit = keyset.currency_unit.to_string(); + let last_index = keyset.last_index as i64; + let public_keys = serde_json::to_string(&keyset.public_keys)?; + sqlx::query!( r#"INSERT INTO keysets (keyset_id, mint_url, currency_unit, last_index, public_keys, active) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT(keyset_id, mint_url) DO UPDATE SET currency_unit = $3, public_keys = $5, active = $6; - "#) - .bind(keyset.keyset_id.to_string()) - .bind(keyset.mint_url.as_str()) - .bind(keyset.currency_unit.to_string()) - .bind(keyset.last_index as i64) - .bind(serde_json::to_string(&keyset.public_keys)?) - .bind(keyset.active) + "#,keyset_id, mint_url, currency_unit, last_index, public_keys, keyset.active) .execute(&mut **tx) .await?; Ok(()) @@ -125,22 +115,23 @@ impl LocalStore for SqliteLocalStore { &self, tx: &mut sqlx::Transaction, ) -> Result, MokshaWalletError> { - let rows = sqlx::query("SELECT * FROM keysets;") + let rows = sqlx::query!("SELECT id, mint_url, keyset_id, currency_unit, active, last_index, public_keys FROM keysets;") .fetch_all(&mut **tx) .await?; - + Ok(rows .iter() .map(|row| { - let id: i64 = row.get(0); - let mint_url: Url = Url::parse(row.get(1)).expect("invalid url in localstore"); + let id: i64 = row.id; + let mint_url: Url = Url::parse(&row.mint_url).expect("invalid URL in localstore"); let keyset_id: KeysetId = - KeysetId::new(row.get(2)).expect("invalid keyset_id in localstore"); - let currency_unit: String = row.get(3); - let active: bool = row.get(4); - let last_index: i64 = row.get(5); + KeysetId::new(&row.keyset_id).expect("invalid keyset_id in localstore"); + let currency_unit: String = row.currency_unit.clone(); + let active: bool = row.active; + let last_index: i64 = row.last_index; + let public_keys: String = row.public_keys.clone(); let public_keys: HashMap = - serde_json::from_str(row.get(6)).expect("invalid json in localstore"); + serde_json::from_str(&public_keys).expect("invalid json in localstore"); Ok(WalletKeyset { id: Some(id as u64), mint_url, @@ -163,10 +154,9 @@ impl LocalStore for SqliteLocalStore { None => return Err(MokshaWalletError::IdNotSet), Some(id) => id as i64, }; + let last_index = keyset.last_index as i64; - sqlx::query(r#"UPDATE keysets SET last_index = $1 WHERE id = $2;"#) - .bind(keyset.last_index as i64) - .bind(id) + sqlx::query!("UPDATE keysets SET last_index = $1 WHERE id = $2;", last_index, id) .execute(&mut **tx) .await?; Ok(()) @@ -177,8 +167,7 @@ impl LocalStore for SqliteLocalStore { tx: &mut sqlx::Transaction, seed_words: &str, ) -> Result<(), MokshaWalletError> { - sqlx::query("INSERT INTO seed (seed_words) VALUES ($1);") - .bind(seed_words) + sqlx::query!("INSERT INTO seed (seed_words) VALUES ($1);", seed_words) .execute(&mut **tx) .await?; Ok(()) @@ -188,12 +177,12 @@ impl LocalStore for SqliteLocalStore { &self, tx: &mut sqlx::Transaction, ) -> Result, MokshaWalletError> { - let row = sqlx::query("SELECT seed_words FROM seed;") + let row = sqlx::query!("SELECT seed_words FROM seed;") .fetch_all(&mut **tx) .await?; match row.len() { 0 => Ok(None), - 1 => Ok(Some(row[0].get(0))), + 1 => Ok(Some(row[0].seed_words.clone())), _ => Err(MokshaWalletError::MultipleSeeds), } } @@ -210,7 +199,6 @@ impl SqliteLocalStore { async fn with_connection_string(connection_string: &str) -> Result { // creates db-file if not already exists - //let pool = sqlx::SqlitePool::connect(connection_string).await?; let pool = sqlx::sqlite::SqlitePoolOptions::new() .acquire_timeout(std::time::Duration::from_secs(5)) .idle_timeout(std::time::Duration::from_secs(5))