fix: use Y

This commit is contained in:
thesimplekid
2024-02-10 16:55:56 +00:00
parent b663228cd2
commit 7c9d9fcf6a
5 changed files with 164 additions and 42 deletions

View File

@@ -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(())
}
}

View File

@@ -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>;
}

View File

@@ -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()?;

View File

@@ -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()) {

View File

@@ -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>;