improve: use bip39 mnemonic for mint secret

This commit is contained in:
thesimplekid
2023-11-19 22:47:09 +00:00
parent 0fe7ccc927
commit 0742ad7754
14 changed files with 85 additions and 30 deletions

View File

@@ -2,7 +2,9 @@ use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
use cashu::nuts::{Id as IdSdk, KeySet as KeySetSdk, KeysetResponse as KeysetResponseSdk};
use cashu::nuts::{
CurrencyUnit, Id as IdSdk, KeySet as KeySetSdk, KeysetResponse as KeysetResponseSdk,
};
use crate::error::Result;
use crate::nuts::nut01::keys::Keys;
@@ -54,7 +56,7 @@ impl KeySet {
Self {
inner: KeySetSdk {
id: *id.as_ref().deref(),
unit,
unit: CurrencyUnit::from_str(&unit).unwrap(),
keys: keys.as_ref().deref().clone(),
},
}
@@ -65,7 +67,7 @@ impl KeySet {
}
pub fn unit(&self) -> String {
self.inner.unit.clone()
self.inner.unit.clone().to_string()
}
pub fn keys(&self) -> Arc<Keys> {

View File

@@ -1,6 +1,8 @@
use std::ops::Deref;
use std::str::FromStr;
use cashu::nuts::nut02::mint::KeySet as KeySetSdk;
use cashu::nuts::CurrencyUnit;
pub struct MintKeySet {
inner: KeySetSdk,
@@ -16,7 +18,12 @@ impl Deref for MintKeySet {
impl MintKeySet {
pub fn generate(secret: String, unit: String, derivation_path: String, max_order: u8) -> Self {
Self {
inner: KeySetSdk::generate(secret, unit, derivation_path, max_order),
inner: KeySetSdk::generate(
secret.as_bytes(),
CurrencyUnit::from_str(&unit).unwrap(),
&derivation_path,
max_order,
),
}
}
}

View File

@@ -1,7 +1,8 @@
use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
use cashu::nuts::KeySetInfo as KeySetInfoSdk;
use cashu::nuts::{CurrencyUnit, KeySetInfo as KeySetInfoSdk};
use crate::Id;
@@ -27,7 +28,7 @@ impl KeySetInfo {
Self {
inner: KeySetInfoSdk {
id: *id.as_ref().deref(),
unit,
unit: CurrencyUnit::from_str(&unit).unwrap(),
},
}
}

View File

@@ -1,7 +1,7 @@
use std::ops::Deref;
use std::str::FromStr;
use cashu::nuts::{Id, KeySet, KeysResponse, KeysetResponse};
use cashu::nuts::{CurrencyUnit, Id, KeySet, KeysResponse, KeysetResponse};
use wasm_bindgen::prelude::*;
use crate::error::{into_err, Result};
@@ -68,7 +68,7 @@ impl JsKeySet {
Self {
inner: KeySet {
id: *id.deref(),
unit,
unit: CurrencyUnit::from_str(&unit).unwrap(),
keys: keys.deref().clone(),
},
}

View File

@@ -1,6 +1,8 @@
use std::ops::Deref;
use std::str::FromStr;
use cashu::nuts::nut02::mint::KeySet;
use cashu::nuts::CurrencyUnit;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(js_name = MintKeySet)]
@@ -32,7 +34,12 @@ impl JsMintKeySet {
max_order: u8,
) -> JsMintKeySet {
Self {
inner: KeySet::generate(secret, unit, derivation_path, max_order),
inner: KeySet::generate(
secret.as_bytes(),
CurrencyUnit::from_str(&unit).unwrap(),
&derivation_path,
max_order,
),
}
}
}

View File

@@ -1,4 +1,5 @@
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, RwLock};
use cashu_ffi::{
@@ -7,6 +8,7 @@ use cashu_ffi::{
Secret, SwapRequest, SwapResponse,
};
use cashu_sdk::mint::Mint as MintSdk;
use cashu_sdk::Mnemonic;
use crate::error::Result;
use crate::types::MintKeySetInfo;
@@ -35,7 +37,7 @@ impl Mint {
Ok(Self {
inner: MintSdk::new(
&secret,
Mnemonic::from_str(&secret).unwrap(),
keysets,
spent_secrets,
// TODO: quotes

View File

@@ -1,7 +1,9 @@
use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
use cashu_sdk::mint::MintKeySetInfo as MintKeySetInfoSdk;
use cashu_sdk::nuts::CurrencyUnit;
use crate::Id;
@@ -36,7 +38,7 @@ impl MintKeySetInfo {
inner: MintKeySetInfoSdk {
id: *id.as_ref().deref(),
active,
unit,
unit: CurrencyUnit::from_str(&unit).unwrap(),
valid_from,
valid_to,
derivation_path,

View File

@@ -1,4 +1,5 @@
use std::ops::Deref;
use std::str::FromStr;
#[cfg(feature = "nut07")]
use cashu_js::nuts::{JsCheckSpendableRequest, JsCheckSpendableResponse};
@@ -9,6 +10,7 @@ use cashu_js::nuts::{
use cashu_js::JsAmount;
use cashu_sdk::mint::Mint;
use cashu_sdk::nuts::{KeySet, KeysResponse};
use cashu_sdk::Mnemonic;
use wasm_bindgen::prelude::*;
use crate::error::{into_err, Result};
@@ -48,7 +50,7 @@ impl JsMint {
let quotes = serde_wasm_bindgen::from_value(quotes).map_err(into_err)?;
Ok(JsMint {
inner: Mint::new(
&secret,
Mnemonic::from_str(&secret).unwrap(),
keyset_info,
spent_secrets,
quotes,

View File

@@ -20,6 +20,7 @@ nut08 = ["cashu/nut08"]
[dependencies]
bip39 = "2.0.0"
cashu = { path = "../cashu" }
serde = { workspace = true }
serde_json = { workspace = true }

View File

@@ -16,6 +16,8 @@ pub mod mint;
pub mod utils;
#[cfg(feature = "wallet")]
pub mod wallet;
pub use bip39::Mnemonic;
pub use cashu::{self, *};
#[cfg(feature = "blocking")]

View File

@@ -14,12 +14,14 @@ use serde::{Deserialize, Serialize};
use tracing::{debug, info};
use crate::types::MeltQuote;
use crate::Mnemonic;
pub struct Mint {
// pub pubkey: PublicKey
_secret: String,
pub keysets: HashMap<Id, nut02::mint::KeySet>,
pub keysets_info: HashMap<Id, MintKeySetInfo>,
// pub pubkey: PublicKey,
mnemonic: Mnemonic,
pub spent_secrets: HashSet<Secret>,
pub pending_secrets: HashSet<Secret>,
pub fee_reserve: FeeReserve,
@@ -28,7 +30,7 @@ pub struct Mint {
impl Mint {
pub fn new(
secret: &str,
mnemonic: Mnemonic,
keysets_info: HashSet<MintKeySetInfo>,
spent_secrets: HashSet<Secret>,
melt_quotes: Vec<MeltQuote>,
@@ -38,7 +40,7 @@ impl Mint {
let mut keysets = HashMap::default();
let mut info = HashMap::default();
let mut active_units: HashSet<String> = HashSet::default();
let mut active_units: HashSet<CurrencyUnit> = HashSet::default();
let melt_quotes = melt_quotes.into_iter().map(|q| (q.id.clone(), q)).collect();
@@ -50,9 +52,9 @@ impl Mint {
}
let keyset = nut02::mint::KeySet::generate(
secret,
&mnemonic.to_seed_normalized(""),
keyset_info.unit.clone(),
keyset_info.derivation_path.clone(),
&keyset_info.derivation_path.clone(),
keyset_info.max_order,
);
@@ -62,7 +64,7 @@ impl Mint {
}
Self {
_secret: secret.to_string(),
mnemonic,
keysets,
melt_quotes,
keysets_info: info,
@@ -105,6 +107,21 @@ impl Mint {
self.keysets.get(id).map(|ks| ks.clone().into())
}
/// Add current keyset to inactive keysets
/// Generate new keyset
pub fn rotate_keyset(&mut self, unit: CurrencyUnit, derivation_path: &str, max_order: u8) {
// TODO: Set old keyset as inactive
let new_keyset = MintKeySet::generate(
&self.mnemonic.to_seed_normalized(""),
unit,
derivation_path,
max_order,
);
self.keysets.insert(new_keyset.id, new_keyset);
}
pub fn process_mint_request(
&mut self,
mint_request: nut04::MintBolt11Request,
@@ -327,7 +344,7 @@ pub struct FeeReserve {
#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MintKeySetInfo {
pub id: Id,
pub unit: String,
pub unit: CurrencyUnit,
pub active: bool,
pub valid_from: u64,
pub valid_to: Option<u64>,

View File

@@ -25,7 +25,7 @@ pub struct BlindedMessage {
pub b: PublicKey,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(rename_all = "lowercase")]
pub enum CurrencyUnit {
#[default]

View File

@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use super::nut01::Keys;
use super::CurrencyUnit;
#[derive(Debug, Error, PartialEq)]
pub enum Error {
@@ -164,7 +165,7 @@ impl KeysetResponse {
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct KeySet {
pub id: Id,
pub unit: String,
pub unit: CurrencyUnit,
pub keys: Keys,
}
@@ -181,7 +182,7 @@ impl From<mint::KeySet> for KeySet {
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct KeySetInfo {
pub id: Id,
pub unit: String,
pub unit: CurrencyUnit,
}
impl From<KeySet> for KeySetInfo {
@@ -203,20 +204,21 @@ pub mod mint {
use super::Id;
use crate::nuts::nut01::mint::{KeyPair, Keys};
use crate::nuts::CurrencyUnit;
use crate::Amount;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct KeySet {
pub id: Id,
pub unit: String,
pub unit: CurrencyUnit,
pub keys: Keys,
}
impl KeySet {
pub fn generate(
secret: impl Into<String>,
unit: impl Into<String>,
derivation_path: impl Into<String>,
secret: &[u8],
unit: CurrencyUnit,
derivation_path: &str,
max_order: u8,
) -> Self {
// Elliptic curve math context
@@ -230,8 +232,8 @@ pub mod mint {
// SHA-256 midstate, for quicker hashing
let mut engine = Sha256::engine();
engine.input(secret.into().as_bytes());
engine.input(derivation_path.into().as_bytes());
engine.input(secret);
engine.input(derivation_path.as_bytes());
for i in 0..max_order {
let amount = Amount::from(2_u64.pow(i as u32));
@@ -249,7 +251,7 @@ pub mod mint {
Self {
id: (&keys).into(),
unit: unit.into(),
unit,
keys,
}
}

View File

@@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};
use crate::nuts::{CurrencyUnit, Proofs};
use crate::nuts::{CurrencyUnit, Id, Proofs};
use crate::{Amount, Bolt11Invoice};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -56,3 +56,13 @@ pub struct MeltQuote {
pub paid: bool,
pub expiry: u64,
}
/// Keyset id
#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct KeysetInfo {
pub id: Id,
pub valid_from: u64,
pub valid_to: Option<u64>,
pub derivation_path: String,
pub max_order: u8,
}