mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-05 13:16:00 +01:00
refactor: store keyset by id
This commit is contained in:
@@ -17,12 +17,15 @@ use tracing::instrument;
|
||||
use super::error::Error;
|
||||
|
||||
const MINTS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mints_table");
|
||||
const MINT_KEYSETS_TABLE: MultimapTableDefinition<&str, &str> =
|
||||
// <Mint_Url, Keyset_id>
|
||||
const MINT_KEYSETS_TABLE: MultimapTableDefinition<&str, &[u8]> =
|
||||
MultimapTableDefinition::new("mint_keysets");
|
||||
// <Keyset_id, KeysetInfo>
|
||||
const KEYSETS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("keysets");
|
||||
const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
|
||||
const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
|
||||
const MINT_KEYS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_keys");
|
||||
// <Y, (Proof, Status, Mint url)>
|
||||
// <Y, Proof Info>
|
||||
const PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("proofs");
|
||||
const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
|
||||
const KEYSET_COUNTER: TableDefinition<&str, u32> = TableDefinition::new("keyset_counter");
|
||||
@@ -62,6 +65,7 @@ impl RedbWalletDatabase {
|
||||
// Open all tables to init a new db
|
||||
let _ = write_txn.open_table(MINTS_TABLE)?;
|
||||
let _ = write_txn.open_multimap_table(MINT_KEYSETS_TABLE)?;
|
||||
let _ = write_txn.open_table(KEYSETS_TABLE)?;
|
||||
let _ = write_txn.open_table(MINT_QUOTES_TABLE)?;
|
||||
let _ = write_txn.open_table(MELT_QUOTES_TABLE)?;
|
||||
let _ = write_txn.open_table(MINT_KEYS_TABLE)?;
|
||||
@@ -166,9 +170,7 @@ impl WalletDatabase for RedbWalletDatabase {
|
||||
table
|
||||
.insert(
|
||||
mint_url.to_string().as_str(),
|
||||
serde_json::to_string(&keyset)
|
||||
.map_err(Error::from)?
|
||||
.as_str(),
|
||||
keyset.id.to_bytes().as_slice(),
|
||||
)
|
||||
.map_err(Error::from)?;
|
||||
}
|
||||
@@ -189,14 +191,52 @@ impl WalletDatabase for RedbWalletDatabase {
|
||||
.open_multimap_table(MINT_KEYSETS_TABLE)
|
||||
.map_err(Error::from)?;
|
||||
|
||||
let keysets = table
|
||||
let keyset_ids: Vec<Id> = table
|
||||
.get(mint_url.to_string().as_str())
|
||||
.map_err(Error::from)?
|
||||
.flatten()
|
||||
.flat_map(|k| serde_json::from_str(k.value()))
|
||||
.flat_map(|k| Id::from_bytes(k.value()))
|
||||
.collect();
|
||||
|
||||
Ok(keysets)
|
||||
let mut keysets = vec![];
|
||||
|
||||
let keysets_t = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
|
||||
|
||||
for keyset_id in keyset_ids {
|
||||
if let Some(keyset) = keysets_t
|
||||
.get(keyset_id.to_bytes().as_slice())
|
||||
.map_err(Error::from)?
|
||||
{
|
||||
let keyset = serde_json::from_str(keyset.value()).map_err(Error::from)?;
|
||||
|
||||
keysets.push(keyset);
|
||||
}
|
||||
}
|
||||
|
||||
match keysets.is_empty() {
|
||||
true => Ok(None),
|
||||
false => Ok(Some(keysets)),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Self::Err> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read().map_err(Into::<Error>::into)?;
|
||||
let table = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
|
||||
|
||||
match table
|
||||
.get(keyset_id.to_bytes().as_slice())
|
||||
.map_err(Error::from)?
|
||||
{
|
||||
Some(keyset) => {
|
||||
let keyset: KeySetInfo =
|
||||
serde_json::from_str(keyset.value()).map_err(Error::from)?;
|
||||
|
||||
Ok(Some(keyset))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::rc::Rc;
|
||||
use std::result::Result;
|
||||
|
||||
@@ -15,7 +15,8 @@ use tokio::sync::Mutex;
|
||||
|
||||
// Tables
|
||||
const MINTS: &str = "mints";
|
||||
const MINT_KEYSETS: &str = "mint_keysets";
|
||||
const MINT_KEYSETS: &str = "keysets_by_mint";
|
||||
const KEYSETS: &str = "keysets";
|
||||
const MINT_KEYS: &str = "mint_keys";
|
||||
const MINT_QUOTES: &str = "mint_quotes";
|
||||
const MELT_QUOTES: &str = "melt_quotes";
|
||||
@@ -23,7 +24,7 @@ const PROOFS: &str = "proofs";
|
||||
const CONFIG: &str = "config";
|
||||
const KEYSET_COUNTER: &str = "keyset_counter";
|
||||
|
||||
const DATABASE_VERSION: u32 = 1;
|
||||
const DATABASE_VERSION: u32 = 2;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
@@ -61,15 +62,20 @@ unsafe impl Sync for RexieWalletDatabase {}
|
||||
impl RexieWalletDatabase {
|
||||
pub async fn new() -> Result<Self, Error> {
|
||||
let rexie = Rexie::builder("cdk")
|
||||
// Set the version of the database to 1.0
|
||||
.version(DATABASE_VERSION)
|
||||
// Add an object store named `employees`
|
||||
.add_object_store(ObjectStore::new(PROOFS).add_index(Index::new("y", "y").unique(true)))
|
||||
.add_object_store(
|
||||
ObjectStore::new(PROOFS)
|
||||
.add_index(Index::new("y", "y").unique(true))
|
||||
.add_index(Index::new("mint_url", "mint_url"))
|
||||
.add_index(Index::new("state", "state"))
|
||||
.add_index(Index::new("unit", "unit")),
|
||||
)
|
||||
.add_object_store(
|
||||
ObjectStore::new(MINTS).add_index(Index::new("mint_url", "mint_url").unique(true)),
|
||||
)
|
||||
.add_object_store(ObjectStore::new(MINT_KEYSETS))
|
||||
.add_object_store(
|
||||
ObjectStore::new(MINT_KEYSETS)
|
||||
ObjectStore::new(KEYSETS)
|
||||
.add_index(Index::new("keyset_id", "keyset_id").unique(true)),
|
||||
)
|
||||
.add_object_store(
|
||||
@@ -175,19 +181,46 @@ impl WalletDatabase for RexieWalletDatabase {
|
||||
let rexie = self.db.lock().await;
|
||||
|
||||
let transaction = rexie
|
||||
.transaction(&[MINT_KEYSETS], TransactionMode::ReadWrite)
|
||||
.transaction(&[MINT_KEYSETS, KEYSETS], TransactionMode::ReadWrite)
|
||||
.map_err(Error::from)?;
|
||||
|
||||
let keysets_store = transaction.store(MINT_KEYSETS).map_err(Error::from)?;
|
||||
let mint_keysets_store = transaction.store(MINT_KEYSETS).map_err(Error::from)?;
|
||||
let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
||||
|
||||
let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
||||
let keysets = serde_wasm_bindgen::to_value(&keysets).map_err(Error::from)?;
|
||||
|
||||
keysets_store
|
||||
.put(&keysets, Some(&mint_url))
|
||||
let mint_keysets = mint_keysets_store
|
||||
.get(&mint_url)
|
||||
.await
|
||||
.map_err(Error::from)?;
|
||||
|
||||
let mut mint_keysets: Option<HashSet<Id>> =
|
||||
serde_wasm_bindgen::from_value(mint_keysets).map_err(Error::from)?;
|
||||
|
||||
let new_keyset_ids: Vec<Id> = keysets.iter().map(|k| k.id).collect();
|
||||
|
||||
mint_keysets
|
||||
.as_mut()
|
||||
.unwrap_or(&mut HashSet::new())
|
||||
.extend(new_keyset_ids);
|
||||
|
||||
let mint_keysets = serde_wasm_bindgen::to_value(&mint_keysets).map_err(Error::from)?;
|
||||
|
||||
mint_keysets_store
|
||||
.put(&mint_keysets, Some(&mint_url))
|
||||
.await
|
||||
.map_err(Error::from)?;
|
||||
|
||||
for keyset in keysets {
|
||||
let id = serde_wasm_bindgen::to_value(&keyset.id).map_err(Error::from)?;
|
||||
let keyset = serde_wasm_bindgen::to_value(&keyset).map_err(Error::from)?;
|
||||
|
||||
keysets_store
|
||||
.put(&keyset, Some(&id))
|
||||
.await
|
||||
.map_err(Error::from)?;
|
||||
}
|
||||
|
||||
transaction.done().await.map_err(Error::from)?;
|
||||
|
||||
Ok(())
|
||||
@@ -200,20 +233,58 @@ impl WalletDatabase for RexieWalletDatabase {
|
||||
let rexie = self.db.lock().await;
|
||||
|
||||
let transaction = rexie
|
||||
.transaction(&[MINT_KEYSETS], TransactionMode::ReadOnly)
|
||||
.transaction(&[MINT_KEYSETS, KEYSETS], TransactionMode::ReadOnly)
|
||||
.map_err(Error::from)?;
|
||||
|
||||
let mints_store = transaction.store(MINT_KEYSETS).map_err(Error::from)?;
|
||||
|
||||
let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
||||
let keysets = mints_store.get(&mint_url).await.map_err(Error::from)?;
|
||||
let mint_keysets = mints_store.get(&mint_url).await.map_err(Error::from)?;
|
||||
|
||||
let keysets: Option<Vec<KeySetInfo>> =
|
||||
serde_wasm_bindgen::from_value(keysets).map_err(Error::from)?;
|
||||
let mint_keysets: Option<HashSet<Id>> =
|
||||
serde_wasm_bindgen::from_value(mint_keysets).map_err(Error::from)?;
|
||||
|
||||
let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
||||
|
||||
let keysets = match mint_keysets {
|
||||
Some(mint_keysets) => {
|
||||
let mut keysets = vec![];
|
||||
|
||||
for mint_keyset in mint_keysets {
|
||||
let id = serde_wasm_bindgen::to_value(&mint_keyset).map_err(Error::from)?;
|
||||
|
||||
let keyset = keysets_store.get(&id).await.map_err(Error::from)?;
|
||||
|
||||
let keyset = serde_wasm_bindgen::from_value(keyset).map_err(Error::from)?;
|
||||
|
||||
keysets.push(keyset);
|
||||
}
|
||||
|
||||
Some(keysets)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
transaction.done().await.map_err(Error::from)?;
|
||||
|
||||
Ok(keysets)
|
||||
}
|
||||
|
||||
async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Self::Err> {
|
||||
let rexie = self.db.lock().await;
|
||||
|
||||
let transaction = rexie
|
||||
.transaction(&[KEYSETS], TransactionMode::ReadOnly)
|
||||
.map_err(Error::from)?;
|
||||
let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
||||
|
||||
let keyset_id = serde_wasm_bindgen::to_value(keyset_id).map_err(Error::from)?;
|
||||
|
||||
let keyset = keysets_store.get(&keyset_id).await.map_err(Error::from)?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(keyset).map_err(Error::from)?)
|
||||
}
|
||||
|
||||
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
|
||||
let rexie = self.db.lock().await;
|
||||
|
||||
|
||||
@@ -64,6 +64,8 @@ pub trait WalletDatabase {
|
||||
&self,
|
||||
mint_url: UncheckedUrl,
|
||||
) -> Result<Option<Vec<KeySetInfo>>, Self::Err>;
|
||||
async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Self::Err>;
|
||||
|
||||
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err>;
|
||||
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err>;
|
||||
async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err>;
|
||||
|
||||
@@ -18,7 +18,8 @@ use crate::url::UncheckedUrl;
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct WalletMemoryDatabase {
|
||||
mints: Arc<RwLock<HashMap<UncheckedUrl, Option<MintInfo>>>>,
|
||||
mint_keysets: Arc<RwLock<HashMap<UncheckedUrl, HashSet<KeySetInfo>>>>,
|
||||
mint_keysets: Arc<RwLock<HashMap<UncheckedUrl, HashSet<Id>>>>,
|
||||
keysets: Arc<RwLock<HashMap<Id, KeySetInfo>>>,
|
||||
mint_quotes: Arc<RwLock<HashMap<String, MintQuote>>>,
|
||||
melt_quotes: Arc<RwLock<HashMap<String, MeltQuote>>>,
|
||||
mint_keys: Arc<RwLock<HashMap<Id, Keys>>>,
|
||||
@@ -39,6 +40,7 @@ impl WalletMemoryDatabase {
|
||||
Self {
|
||||
mints: Arc::new(RwLock::new(HashMap::new())),
|
||||
mint_keysets: Arc::new(RwLock::new(HashMap::new())),
|
||||
keysets: Arc::new(RwLock::new(HashMap::new())),
|
||||
mint_quotes: Arc::new(RwLock::new(
|
||||
mint_quotes.into_iter().map(|q| (q.id.clone(), q)).collect(),
|
||||
)),
|
||||
@@ -83,10 +85,19 @@ impl WalletDatabase for WalletMemoryDatabase {
|
||||
mint_url: UncheckedUrl,
|
||||
keysets: Vec<KeySetInfo>,
|
||||
) -> Result<(), Error> {
|
||||
let mut current_keysets = self.mint_keysets.write().await;
|
||||
let mut current_mint_keysets = self.mint_keysets.write().await;
|
||||
let mut current_keysets = self.keysets.write().await;
|
||||
|
||||
let mint_keysets = current_keysets.entry(mint_url).or_insert(HashSet::new());
|
||||
mint_keysets.extend(keysets);
|
||||
for keyset in keysets {
|
||||
current_mint_keysets
|
||||
.entry(mint_url.clone())
|
||||
.and_modify(|ks| {
|
||||
ks.insert(keyset.id);
|
||||
})
|
||||
.or_insert(HashSet::from_iter(vec![keyset.id]));
|
||||
|
||||
current_keysets.insert(keyset.id, keyset);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -95,12 +106,26 @@ impl WalletDatabase for WalletMemoryDatabase {
|
||||
&self,
|
||||
mint_url: UncheckedUrl,
|
||||
) -> Result<Option<Vec<KeySetInfo>>, Error> {
|
||||
Ok(self
|
||||
.mint_keysets
|
||||
.read()
|
||||
.await
|
||||
.get(&mint_url)
|
||||
.map(|ks| ks.iter().cloned().collect()))
|
||||
match self.mint_keysets.read().await.get(&mint_url) {
|
||||
Some(keyset_ids) => {
|
||||
let mut keysets = vec![];
|
||||
|
||||
let db_keysets = self.keysets.read().await;
|
||||
|
||||
for id in keyset_ids {
|
||||
if let Some(keyset) = db_keysets.get(id) {
|
||||
keysets.push(keyset.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(keysets))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Error> {
|
||||
Ok(self.keysets.read().await.get(keyset_id).cloned())
|
||||
}
|
||||
|
||||
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Error> {
|
||||
|
||||
@@ -694,14 +694,13 @@ impl Wallet {
|
||||
.post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
|
||||
.await?;
|
||||
|
||||
let active_keys = self.active_keys(mint_url, unit).await?.unwrap();
|
||||
|
||||
let mut post_swap_proofs = construct_proofs(
|
||||
swap_response.signatures,
|
||||
pre_swap.pre_mint_secrets.rs(),
|
||||
pre_swap.pre_mint_secrets.secrets(),
|
||||
&self
|
||||
.active_keys(mint_url, unit)
|
||||
.await?
|
||||
.ok_or(Error::UnknownKey)?,
|
||||
&active_keys,
|
||||
)?;
|
||||
|
||||
let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?;
|
||||
@@ -793,7 +792,7 @@ impl Wallet {
|
||||
proofs: Proofs,
|
||||
spending_conditions: Option<SpendingConditions>,
|
||||
) -> Result<PreSwap, Error> {
|
||||
let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?;
|
||||
let active_keyset_id = self.active_mint_keyset(mint_url, unit).await.unwrap();
|
||||
|
||||
// Desired amount is either amount passwed or value of all proof
|
||||
let proofs_total = proofs.iter().map(|p| p.amount).sum();
|
||||
@@ -1047,11 +1046,10 @@ impl Wallet {
|
||||
.collect();
|
||||
}
|
||||
|
||||
let mint_keysets = self
|
||||
.localstore
|
||||
.get_mint_keysets(mint_url.clone())
|
||||
.await?
|
||||
.ok_or(Error::UnknownKey)?;
|
||||
let mint_keysets = match self.localstore.get_mint_keysets(mint_url.clone()).await? {
|
||||
Some(keysets) => keysets,
|
||||
None => self.get_mint_keysets(&mint_url).await?,
|
||||
};
|
||||
|
||||
let (active, inactive): (HashSet<KeySetInfo>, HashSet<KeySetInfo>) = mint_keysets
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user