mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-05 05:06:14 +01:00
fix: use Y
This commit is contained in:
@@ -2,6 +2,8 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cashu::dhke::hash_to_curve;
|
||||
use cashu::k256;
|
||||
use cashu::nuts::nut02::mint::KeySet;
|
||||
use cashu::nuts::{CurrencyUnit, Id, MintInfo, Proof, Proofs};
|
||||
use cashu::secret::Secret;
|
||||
@@ -17,8 +19,8 @@ pub struct MemoryLocalStore {
|
||||
keysets: Arc<Mutex<HashMap<Id, KeySet>>>,
|
||||
mint_quotes: Arc<Mutex<HashMap<String, MintQuote>>>,
|
||||
melt_quotes: Arc<Mutex<HashMap<String, MeltQuote>>>,
|
||||
pending_proofs: Arc<Mutex<HashMap<Secret, Proof>>>,
|
||||
spent_proofs: Arc<Mutex<HashMap<Secret, Proof>>>,
|
||||
pending_proofs: Arc<Mutex<HashMap<Vec<u8>, Proof>>>,
|
||||
spent_proofs: Arc<Mutex<HashMap<Vec<u8>, Proof>>>,
|
||||
}
|
||||
|
||||
impl MemoryLocalStore {
|
||||
@@ -30,8 +32,8 @@ impl MemoryLocalStore {
|
||||
melt_quotes: Vec<MeltQuote>,
|
||||
pending_proofs: Proofs,
|
||||
spent_proofs: Proofs,
|
||||
) -> Self {
|
||||
Self {
|
||||
) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
mint_info: Arc::new(Mutex::new(mint_info)),
|
||||
active_keysets: Arc::new(Mutex::new(active_keysets)),
|
||||
keysets: Arc::new(Mutex::new(keysets.into_iter().map(|k| (k.id, k)).collect())),
|
||||
@@ -44,16 +46,30 @@ impl MemoryLocalStore {
|
||||
pending_proofs: Arc::new(Mutex::new(
|
||||
pending_proofs
|
||||
.into_iter()
|
||||
.map(|p| (p.secret.clone(), p))
|
||||
.map(|p| {
|
||||
(
|
||||
hash_to_curve(&p.secret.to_bytes().unwrap())
|
||||
.to_sec1_bytes()
|
||||
.to_vec(),
|
||||
p,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
spent_proofs: Arc::new(Mutex::new(
|
||||
spent_proofs
|
||||
.into_iter()
|
||||
.map(|p| (p.secret.clone(), p))
|
||||
.map(|p| {
|
||||
(
|
||||
hash_to_curve(&p.secret.to_bytes().unwrap())
|
||||
.to_sec1_bytes()
|
||||
.to_vec(),
|
||||
p,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,31 +154,73 @@ impl LocalStore for MemoryLocalStore {
|
||||
}
|
||||
|
||||
async fn add_spent_proof(&self, proof: Proof) -> Result<(), Error> {
|
||||
let secret_point = hash_to_curve(&proof.secret.to_bytes()?);
|
||||
self.spent_proofs
|
||||
.lock()
|
||||
.await
|
||||
.insert(proof.secret.clone(), proof);
|
||||
.insert(secret_point.to_sec1_bytes().to_vec(), proof);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
Ok(self.spent_proofs.lock().await.get(secret).cloned())
|
||||
async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
Ok(self
|
||||
.spent_proofs
|
||||
.lock()
|
||||
.await
|
||||
.get(&hash_to_curve(&secret.to_bytes()?).to_sec1_bytes().to_vec())
|
||||
.cloned())
|
||||
}
|
||||
|
||||
async fn get_spent_proof_by_hash(
|
||||
&self,
|
||||
secret: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error> {
|
||||
Ok(self
|
||||
.spent_proofs
|
||||
.lock()
|
||||
.await
|
||||
.get(&secret.to_sec1_bytes().to_vec())
|
||||
.cloned())
|
||||
}
|
||||
|
||||
async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error> {
|
||||
self.pending_proofs
|
||||
.lock()
|
||||
.await
|
||||
.insert(proof.secret.clone(), proof);
|
||||
self.pending_proofs.lock().await.insert(
|
||||
hash_to_curve(&proof.secret.to_bytes()?)
|
||||
.to_sec1_bytes()
|
||||
.to_vec(),
|
||||
proof,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
Ok(self.pending_proofs.lock().await.get(secret).cloned())
|
||||
async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
let secret_point = hash_to_curve(&secret.to_bytes()?);
|
||||
Ok(self
|
||||
.pending_proofs
|
||||
.lock()
|
||||
.await
|
||||
.get(&secret_point.to_sec1_bytes().to_vec())
|
||||
.cloned())
|
||||
}
|
||||
|
||||
async fn get_pending_proof_by_hash(
|
||||
&self,
|
||||
secret: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error> {
|
||||
Ok(self
|
||||
.pending_proofs
|
||||
.lock()
|
||||
.await
|
||||
.get(&secret.to_sec1_bytes().to_vec())
|
||||
.cloned())
|
||||
}
|
||||
|
||||
async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error> {
|
||||
self.pending_proofs.lock().await.remove(secret);
|
||||
let secret_point = hash_to_curve(&secret.to_bytes()?);
|
||||
self.pending_proofs
|
||||
.lock()
|
||||
.await
|
||||
.remove(&secret_point.to_sec1_bytes().to_vec());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ pub mod redb_store;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cashu::k256;
|
||||
use cashu::nuts::nut02::mint::KeySet;
|
||||
use cashu::nuts::{CurrencyUnit, Id, MintInfo, Proof};
|
||||
use cashu::secret::Secret;
|
||||
@@ -43,6 +44,8 @@ pub enum Error {
|
||||
Cashu(#[from] cashu::error::Error),
|
||||
#[error("`{0}`")]
|
||||
CashuNut02(#[from] cashu::nuts::nut02::Error),
|
||||
#[error("`{0}`")]
|
||||
Secret(#[from] cashu::secret::Error),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -69,9 +72,17 @@ pub trait LocalStore {
|
||||
async fn get_keysets(&self) -> Result<Vec<KeySet>, Error>;
|
||||
|
||||
async fn add_spent_proof(&self, proof: Proof) -> Result<(), Error>;
|
||||
async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
|
||||
async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
|
||||
async fn get_spent_proof_by_hash(
|
||||
&self,
|
||||
secret: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error>;
|
||||
|
||||
async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error>;
|
||||
async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
|
||||
async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
|
||||
async fn get_pending_proof_by_hash(
|
||||
&self,
|
||||
secret: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error>;
|
||||
async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cashu::dhke::hash_to_curve;
|
||||
use cashu::k256;
|
||||
use cashu::nuts::{CurrencyUnit, Id, MintInfo, MintKeySet as KeySet, Proof};
|
||||
use cashu::secret::Secret;
|
||||
use cashu::types::{MeltQuote, MintQuote};
|
||||
@@ -16,8 +18,8 @@ const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("
|
||||
const KEYSETS_TABLE: TableDefinition<&str, &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 PENDING_PROOFS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("pending_proofs");
|
||||
const SPENT_PROOFS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("spent_proofs");
|
||||
const PENDING_PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("pending_proofs");
|
||||
const SPENT_PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("spent_proofs");
|
||||
const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -275,7 +277,9 @@ impl LocalStore for RedbLocalStore {
|
||||
{
|
||||
let mut table = write_txn.open_table(SPENT_PROOFS_TABLE)?;
|
||||
table.insert(
|
||||
proof.secret.to_string().as_str(),
|
||||
hash_to_curve(&proof.secret.to_bytes()?)
|
||||
.to_sec1_bytes()
|
||||
.as_ref(),
|
||||
serde_json::to_string(&proof)?.as_str(),
|
||||
)?;
|
||||
}
|
||||
@@ -286,16 +290,31 @@ impl LocalStore for RedbLocalStore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
async fn get_spent_proof_by_hash(
|
||||
&self,
|
||||
secret_point: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read()?;
|
||||
let table = read_txn.open_table(SPENT_PROOFS_TABLE)?;
|
||||
|
||||
let quote = table.get(secret.to_string().as_str())?;
|
||||
let proof = table.get(secret_point.to_sec1_bytes().as_ref())?;
|
||||
|
||||
Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
|
||||
}
|
||||
|
||||
async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read()?;
|
||||
let table = read_txn.open_table(SPENT_PROOFS_TABLE)?;
|
||||
|
||||
let secret_hash = hash_to_curve(&secret.to_bytes()?);
|
||||
|
||||
let proof = table.get(secret_hash.to_sec1_bytes().as_ref())?;
|
||||
|
||||
debug!("Checking secret: {}", secret.to_string());
|
||||
|
||||
Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
|
||||
Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
|
||||
}
|
||||
|
||||
async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error> {
|
||||
@@ -306,7 +325,9 @@ impl LocalStore for RedbLocalStore {
|
||||
{
|
||||
let mut table = write_txn.open_table(PENDING_PROOFS_TABLE)?;
|
||||
table.insert(
|
||||
proof.secret.to_string().as_str(),
|
||||
hash_to_curve(&proof.secret.to_bytes()?)
|
||||
.to_sec1_bytes()
|
||||
.as_ref(),
|
||||
serde_json::to_string(&proof)?.as_str(),
|
||||
)?;
|
||||
}
|
||||
@@ -315,14 +336,29 @@ impl LocalStore for RedbLocalStore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
async fn get_pending_proof_by_hash(
|
||||
&self,
|
||||
secret_point: &k256::PublicKey,
|
||||
) -> Result<Option<Proof>, Error> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read()?;
|
||||
let table = read_txn.open_table(MELT_QUOTES_TABLE)?;
|
||||
let table = read_txn.open_table(PENDING_PROOFS_TABLE)?;
|
||||
|
||||
let quote = table.get(secret.to_string().as_str())?;
|
||||
let proof = table.get(secret_point.to_sec1_bytes().as_ref())?;
|
||||
|
||||
Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
|
||||
Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
|
||||
}
|
||||
|
||||
async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read()?;
|
||||
let table = read_txn.open_table(PENDING_PROOFS_TABLE)?;
|
||||
|
||||
let secret_hash = hash_to_curve(&secret.to_bytes()?);
|
||||
|
||||
let proof = table.get(secret_hash.to_sec1_bytes().as_ref())?;
|
||||
|
||||
Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
|
||||
}
|
||||
|
||||
async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error> {
|
||||
@@ -332,7 +368,8 @@ impl LocalStore for RedbLocalStore {
|
||||
|
||||
{
|
||||
let mut table = write_txn.open_table(PENDING_PROOFS_TABLE)?;
|
||||
table.remove(secret.to_string().as_str())?;
|
||||
let secret_hash = hash_to_curve(&secret.to_bytes()?);
|
||||
table.remove(secret_hash.to_sec1_bytes().as_ref())?;
|
||||
}
|
||||
write_txn.commit()?;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cashu::dhke::{sign_message, verify_message};
|
||||
use cashu::dhke::{hash_to_curve, sign_message, verify_message};
|
||||
use cashu::error::ErrorResponse;
|
||||
#[cfg(feature = "nut07")]
|
||||
use cashu::nuts::nut07::{ProofState, State};
|
||||
@@ -11,7 +11,6 @@ use cashu::nuts::{
|
||||
};
|
||||
#[cfg(feature = "nut07")]
|
||||
use cashu::nuts::{CheckStateRequest, CheckStateResponse};
|
||||
use cashu::secret::Secret;
|
||||
use cashu::types::{MeltQuote, MintQuote};
|
||||
use cashu::Amount;
|
||||
use http::StatusCode;
|
||||
@@ -52,6 +51,8 @@ pub enum Error {
|
||||
Cashu(#[from] cashu::error::mint::Error),
|
||||
#[error("`{0}`")]
|
||||
Localstore(#[from] localstore::Error),
|
||||
#[error("`{0}`")]
|
||||
Secret(#[from] cashu::secret::Error),
|
||||
#[error("Unknown quote")]
|
||||
UnknownQuote,
|
||||
#[error("Cannot have multiple units")]
|
||||
@@ -353,10 +354,11 @@ impl Mint {
|
||||
|
||||
let proof_count = swap_request.inputs.len();
|
||||
|
||||
let secrets: HashSet<Secret> = swap_request
|
||||
let secrets: HashSet<Vec<u8>> = swap_request
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|p| p.secret.clone())
|
||||
.flat_map(|p| p.secret.to_bytes())
|
||||
.map(|p| hash_to_curve(&p).to_sec1_bytes().to_vec())
|
||||
.collect();
|
||||
|
||||
// Check that there are no duplicate proofs in request
|
||||
@@ -420,7 +422,7 @@ impl Mint {
|
||||
async fn verify_proof(&self, proof: &Proof) -> Result<(), Error> {
|
||||
if self
|
||||
.localstore
|
||||
.get_spent_proof(&proof.secret)
|
||||
.get_spent_proof_by_secret(&proof.secret)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
@@ -429,7 +431,7 @@ impl Mint {
|
||||
|
||||
if self
|
||||
.localstore
|
||||
.get_pending_proof(&proof.secret)
|
||||
.get_pending_proof_by_secret(&proof.secret)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
@@ -463,9 +465,19 @@ impl Mint {
|
||||
let mut states = Vec::with_capacity(check_state.secrets.len());
|
||||
|
||||
for secret in &check_state.secrets {
|
||||
let state = if self.localstore.get_spent_proof(secret).await?.is_some() {
|
||||
let state = if self
|
||||
.localstore
|
||||
.get_spent_proof_by_secret(secret)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
State::Spent
|
||||
} else if self.localstore.get_pending_proof(secret).await?.is_some() {
|
||||
} else if self
|
||||
.localstore
|
||||
.get_pending_proof_by_secret(secret)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
State::Pending
|
||||
} else {
|
||||
State::Unspent
|
||||
@@ -545,7 +557,12 @@ impl Mint {
|
||||
return Err(Error::MultipleUnits);
|
||||
}
|
||||
|
||||
let secrets: HashSet<&Secret> = melt_request.inputs.iter().map(|p| &p.secret).collect();
|
||||
let secrets: HashSet<Vec<u8>> = melt_request
|
||||
.inputs
|
||||
.iter()
|
||||
.flat_map(|p| p.secret.to_bytes())
|
||||
.map(|p| hash_to_curve(&p).to_sec1_bytes().to_vec())
|
||||
.collect();
|
||||
|
||||
// Ensure proofs are unique and not being double spent
|
||||
if melt_request.inputs.len().ne(&secrets.len()) {
|
||||
|
||||
@@ -11,7 +11,6 @@ pub mod utils;
|
||||
|
||||
pub use amount::Amount;
|
||||
pub use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
pub use lightning_invoice;
|
||||
pub use lightning_invoice::Bolt11Invoice;
|
||||
|
||||
pub use {k256, lightning_invoice};
|
||||
pub type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||
|
||||
Reference in New Issue
Block a user