|
@@ -6,64 +6,41 @@ use bitcoin::secp256k1::{self, All, Secp256k1};
|
|
|
use cdk_common::database;
|
|
use cdk_common::database;
|
|
|
use cdk_common::error::Error;
|
|
use cdk_common::error::Error;
|
|
|
use cdk_common::mint::MintKeySetInfo;
|
|
use cdk_common::mint::MintKeySetInfo;
|
|
|
-use cdk_common::nuts::{CurrencyUnit, Id, MintKeySet};
|
|
|
|
|
|
|
+use cdk_common::nuts::{CurrencyUnit, MintKeySet};
|
|
|
use cdk_common::util::unix_time;
|
|
use cdk_common::util::unix_time;
|
|
|
|
|
|
|
|
-/// Initialize keysets and returns a [`Result`] with a tuple of the following:
|
|
|
|
|
-/// * a [`HashMap`] mapping each active keyset `Id` to `MintKeySet`
|
|
|
|
|
-/// * a [`Vec`] of `CurrencyUnit` containing active keysets units
|
|
|
|
|
|
|
+/// Initialize keysets
|
|
|
pub async fn init_keysets(
|
|
pub async fn init_keysets(
|
|
|
xpriv: Xpriv,
|
|
xpriv: Xpriv,
|
|
|
secp_ctx: &Secp256k1<All>,
|
|
secp_ctx: &Secp256k1<All>,
|
|
|
localstore: &Arc<dyn database::MintKeysDatabase<Err = database::Error> + Send + Sync>,
|
|
localstore: &Arc<dyn database::MintKeysDatabase<Err = database::Error> + Send + Sync>,
|
|
|
supported_units: &HashMap<CurrencyUnit, (u64, u8)>,
|
|
supported_units: &HashMap<CurrencyUnit, (u64, u8)>,
|
|
|
- custom_paths: &HashMap<CurrencyUnit, DerivationPath>,
|
|
|
|
|
-) -> Result<(HashMap<Id, MintKeySet>, Vec<CurrencyUnit>), Error> {
|
|
|
|
|
- let mut active_keysets: HashMap<Id, MintKeySet> = HashMap::new();
|
|
|
|
|
- let mut active_keyset_units: Vec<CurrencyUnit> = vec![];
|
|
|
|
|
-
|
|
|
|
|
- // Get keysets info from DB
|
|
|
|
|
|
|
+) -> Result<(), Error> {
|
|
|
let keysets_infos = localstore.get_keyset_infos().await?;
|
|
let keysets_infos = localstore.get_keyset_infos().await?;
|
|
|
-
|
|
|
|
|
let mut tx = localstore.begin_transaction().await?;
|
|
let mut tx = localstore.begin_transaction().await?;
|
|
|
- if !keysets_infos.is_empty() {
|
|
|
|
|
- tracing::debug!("Setting all saved keysets to inactive");
|
|
|
|
|
- for keyset in keysets_infos.clone() {
|
|
|
|
|
- // Set all to in active
|
|
|
|
|
- let mut keyset = keyset;
|
|
|
|
|
- keyset.active = false;
|
|
|
|
|
- tx.add_keyset_info(keyset).await?;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- let keysets_by_unit: HashMap<CurrencyUnit, Vec<MintKeySetInfo>> =
|
|
|
|
|
- keysets_infos.iter().fold(HashMap::new(), |mut acc, ks| {
|
|
|
|
|
- acc.entry(ks.unit.clone()).or_default().push(ks.clone());
|
|
|
|
|
- acc
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ let keysets_by_unit: HashMap<CurrencyUnit, Vec<MintKeySetInfo>> =
|
|
|
|
|
+ keysets_infos.iter().fold(HashMap::new(), |mut acc, ks| {
|
|
|
|
|
+ acc.entry(ks.unit.clone()).or_default().push(ks.clone());
|
|
|
|
|
+ acc
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- for (unit, keysets) in keysets_by_unit {
|
|
|
|
|
|
|
+ for (unit, keysets) in keysets_by_unit {
|
|
|
|
|
+ // We only care about units that are supported
|
|
|
|
|
+ if let Some((input_fee_ppk, max_order)) = supported_units.get(&unit) {
|
|
|
let mut keysets = keysets;
|
|
let mut keysets = keysets;
|
|
|
keysets.sort_by(|a, b| b.derivation_path_index.cmp(&a.derivation_path_index));
|
|
keysets.sort_by(|a, b| b.derivation_path_index.cmp(&a.derivation_path_index));
|
|
|
|
|
|
|
|
- // Get the keyset with the highest counter
|
|
|
|
|
- let highest_index_keyset = keysets
|
|
|
|
|
- .first()
|
|
|
|
|
- .cloned()
|
|
|
|
|
- .expect("unit will not be added to hashmap if empty");
|
|
|
|
|
-
|
|
|
|
|
- let keysets: Vec<MintKeySetInfo> = keysets
|
|
|
|
|
- .into_iter()
|
|
|
|
|
- .filter(|ks| ks.derivation_path_index.is_some())
|
|
|
|
|
- .collect();
|
|
|
|
|
-
|
|
|
|
|
- if let Some((input_fee_ppk, max_order)) = supported_units.get(&unit) {
|
|
|
|
|
- if !keysets.is_empty()
|
|
|
|
|
- && highest_index_keyset.input_fee_ppk == *input_fee_ppk
|
|
|
|
|
|
|
+ if let Some(highest_index_keyset) = keysets.first() {
|
|
|
|
|
+ // Check if it matches our criteria
|
|
|
|
|
+ if highest_index_keyset.input_fee_ppk == *input_fee_ppk
|
|
|
&& highest_index_keyset.amounts.len() == (*max_order as usize)
|
|
&& highest_index_keyset.amounts.len() == (*max_order as usize)
|
|
|
{
|
|
{
|
|
|
tracing::debug!("Current highest index keyset matches expect fee and max order. Setting active");
|
|
tracing::debug!("Current highest index keyset matches expect fee and max order. Setting active");
|
|
|
let id = highest_index_keyset.id;
|
|
let id = highest_index_keyset.id;
|
|
|
- let keyset = MintKeySet::generate_from_xpriv(
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Validate we can generate it (sanity check)
|
|
|
|
|
+ let _ = MintKeySet::generate_from_xpriv(
|
|
|
secp_ctx,
|
|
secp_ctx,
|
|
|
xpriv,
|
|
xpriv,
|
|
|
&highest_index_keyset.amounts,
|
|
&highest_index_keyset.amounts,
|
|
@@ -71,53 +48,21 @@ pub async fn init_keysets(
|
|
|
highest_index_keyset.derivation_path.clone(),
|
|
highest_index_keyset.derivation_path.clone(),
|
|
|
highest_index_keyset.input_fee_ppk,
|
|
highest_index_keyset.input_fee_ppk,
|
|
|
highest_index_keyset.final_expiry,
|
|
highest_index_keyset.final_expiry,
|
|
|
- cdk_common::nut02::KeySetVersion::Version00,
|
|
|
|
|
|
|
+ highest_index_keyset.id.get_version(),
|
|
|
);
|
|
);
|
|
|
- active_keysets.insert(id, keyset);
|
|
|
|
|
- let mut keyset_info = highest_index_keyset;
|
|
|
|
|
- keyset_info.active = true;
|
|
|
|
|
- tx.add_keyset_info(keyset_info).await?;
|
|
|
|
|
- active_keyset_units.push(unit.clone());
|
|
|
|
|
- tx.set_active_keyset(unit, id).await?;
|
|
|
|
|
- } else {
|
|
|
|
|
- // Check to see if there are not keysets by this unit
|
|
|
|
|
- let derivation_path_index = if keysets.is_empty() {
|
|
|
|
|
- 1
|
|
|
|
|
- } else {
|
|
|
|
|
- highest_index_keyset.derivation_path_index.unwrap_or(0) + 1
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- let derivation_path = match custom_paths.get(&unit) {
|
|
|
|
|
- Some(path) => path.clone(),
|
|
|
|
|
- None => derivation_path_from_unit(unit.clone(), derivation_path_index)
|
|
|
|
|
- .ok_or(Error::UnsupportedUnit)?,
|
|
|
|
|
- };
|
|
|
|
|
|
|
|
|
|
- let (keyset, keyset_info) = create_new_keyset(
|
|
|
|
|
- secp_ctx,
|
|
|
|
|
- xpriv,
|
|
|
|
|
- derivation_path,
|
|
|
|
|
- Some(derivation_path_index),
|
|
|
|
|
- unit.clone(),
|
|
|
|
|
- &highest_index_keyset.amounts,
|
|
|
|
|
- *input_fee_ppk,
|
|
|
|
|
- // TODO: add Mint settings for a final expiry of newly generated keysets
|
|
|
|
|
- None,
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- let id = keyset_info.id;
|
|
|
|
|
|
|
+ let mut keyset_info = highest_index_keyset.clone();
|
|
|
|
|
+ keyset_info.active = true;
|
|
|
tx.add_keyset_info(keyset_info).await?;
|
|
tx.add_keyset_info(keyset_info).await?;
|
|
|
tx.set_active_keyset(unit.clone(), id).await?;
|
|
tx.set_active_keyset(unit.clone(), id).await?;
|
|
|
- active_keysets.insert(id, keyset);
|
|
|
|
|
- active_keyset_units.push(unit.clone());
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
tx.commit().await?;
|
|
tx.commit().await?;
|
|
|
|
|
|
|
|
- Ok((active_keysets, active_keyset_units))
|
|
|
|
|
|
|
+ Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Generate new [`MintKeySetInfo`] from path
|
|
/// Generate new [`MintKeySetInfo`] from path
|
|
@@ -132,7 +77,14 @@ pub fn create_new_keyset<C: secp256k1::Signing>(
|
|
|
amounts: &[u64],
|
|
amounts: &[u64],
|
|
|
input_fee_ppk: u64,
|
|
input_fee_ppk: u64,
|
|
|
final_expiry: Option<u64>,
|
|
final_expiry: Option<u64>,
|
|
|
|
|
+ use_keyset_v2: bool,
|
|
|
) -> (MintKeySet, MintKeySetInfo) {
|
|
) -> (MintKeySet, MintKeySetInfo) {
|
|
|
|
|
+ let version = if use_keyset_v2 {
|
|
|
|
|
+ cdk_common::nut02::KeySetVersion::Version01
|
|
|
|
|
+ } else {
|
|
|
|
|
+ cdk_common::nut02::KeySetVersion::Version00
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
let keyset = MintKeySet::generate(
|
|
let keyset = MintKeySet::generate(
|
|
|
secp,
|
|
secp,
|
|
|
xpriv
|
|
xpriv
|
|
@@ -142,8 +94,7 @@ pub fn create_new_keyset<C: secp256k1::Signing>(
|
|
|
amounts,
|
|
amounts,
|
|
|
input_fee_ppk,
|
|
input_fee_ppk,
|
|
|
final_expiry,
|
|
final_expiry,
|
|
|
- // TODO: change this to Version01 to generate keysets v2
|
|
|
|
|
- cdk_common::nut02::KeySetVersion::Version00,
|
|
|
|
|
|
|
+ version,
|
|
|
);
|
|
);
|
|
|
let keyset_info = MintKeySetInfo {
|
|
let keyset_info = MintKeySetInfo {
|
|
|
id: keyset.id,
|
|
id: keyset.id,
|