refactor(mint): check ys spendable

This commit is contained in:
thesimplekid
2024-07-16 09:50:33 +01:00
parent 373a4203b2
commit e51f81f441

View File

@@ -614,38 +614,16 @@ impl Mint {
let proof_count = swap_request.inputs.len(); let proof_count = swap_request.inputs.len();
let secrets: Vec<PublicKey> = swap_request let ys: Vec<PublicKey> = swap_request
.inputs .inputs
.iter() .iter()
.flat_map(|p| hash_to_curve(&p.secret.to_bytes())) .flat_map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect(); .collect();
let pending_proofs: Proofs = self self.check_ys_unspent(&ys).await?;
.localstore
.get_pending_proofs_by_ys(&secrets)
.await?
.into_iter()
.flatten()
.collect();
if !pending_proofs.is_empty() {
return Err(Error::TokenPending);
}
let spent_proofs: Proofs = self
.localstore
.get_spent_proofs_by_ys(&secrets)
.await?
.into_iter()
.flatten()
.collect();
if !spent_proofs.is_empty() {
return Err(Error::TokenAlreadySpent);
}
// Check that there are no duplicate proofs in request // Check that there are no duplicate proofs in request
if secrets if ys
.iter() .iter()
.collect::<HashSet<&PublicKey>>() .collect::<HashSet<&PublicKey>>()
.len() .len()
@@ -771,8 +749,6 @@ impl Mint {
&self, &self,
check_state: &CheckStateRequest, check_state: &CheckStateRequest,
) -> Result<CheckStateResponse, Error> { ) -> Result<CheckStateResponse, Error> {
let mut states = Vec::with_capacity(check_state.ys.len());
let spent_proofs = self let spent_proofs = self
.localstore .localstore
.get_spent_proofs_by_ys(&check_state.ys) .get_spent_proofs_by_ys(&check_state.ys)
@@ -782,50 +758,39 @@ impl Mint {
.get_pending_proofs_by_ys(&check_state.ys) .get_pending_proofs_by_ys(&check_state.ys)
.await?; .await?;
for ((spent, pending), y) in spent_proofs let states = spent_proofs
.iter() .iter()
.zip(&pending_proofs) .zip(&pending_proofs)
.zip(&check_state.ys) .zip(&check_state.ys)
{ .map(|((spent, pending), y)| {
let state = match (spent, pending) { let state = match (spent, pending) {
(None, None) => State::Unspent, (None, None) => State::Unspent,
(Some(_), None) => State::Spent, (Some(_), None) => State::Spent,
(None, Some(_)) => State::Pending, (None, Some(_)) => State::Pending,
(Some(_), Some(_)) => { (Some(_), Some(_)) => {
tracing::error!("Proof should not be both pending and spent. Assuming Spent"); tracing::error!(
State::Spent "Proof should not be both pending and spent. Assuming Spent"
);
State::Spent
}
};
ProofState {
y: *y,
state,
witness: None,
} }
};
states.push(ProofState {
y: *y,
state,
witness: None,
}) })
} .collect();
Ok(CheckStateResponse { states }) Ok(CheckStateResponse { states })
} }
/// Verify melt request is valid /// Check Tokens are not spent or pending
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn verify_melt_request( pub async fn check_ys_unspent(&self, ys: &[PublicKey]) -> Result<(), Error> {
&self,
melt_request: &MeltBolt11Request,
) -> Result<MeltQuote, Error> {
let secrets: Vec<PublicKey> = melt_request
.inputs
.iter()
.flat_map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect();
// Ensure proofs are unique and not being double spent
if melt_request.inputs.len() != secrets.iter().collect::<HashSet<_>>().len() {
return Err(Error::DuplicateProofs);
}
let pending_proofs: Proofs = self let pending_proofs: Proofs = self
.localstore .localstore
.get_pending_proofs_by_ys(&secrets) .get_pending_proofs_by_ys(ys)
.await? .await?
.into_iter() .into_iter()
.flatten() .flatten()
@@ -837,7 +802,7 @@ impl Mint {
let spent_proofs: Proofs = self let spent_proofs: Proofs = self
.localstore .localstore
.get_spent_proofs_by_ys(&secrets) .get_spent_proofs_by_ys(ys)
.await? .await?
.into_iter() .into_iter()
.flatten() .flatten()
@@ -847,6 +812,28 @@ impl Mint {
return Err(Error::TokenAlreadySpent); return Err(Error::TokenAlreadySpent);
} }
Ok(())
}
/// Verify melt request is valid
#[instrument(skip_all)]
pub async fn verify_melt_request(
&self,
melt_request: &MeltBolt11Request,
) -> Result<MeltQuote, Error> {
let ys: Vec<PublicKey> = melt_request
.inputs
.iter()
.flat_map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect();
// Ensure proofs are unique and not being double spent
if melt_request.inputs.len() != ys.iter().collect::<HashSet<_>>().len() {
return Err(Error::DuplicateProofs);
}
self.check_ys_unspent(&ys).await?;
for proof in &melt_request.inputs { for proof in &melt_request.inputs {
self.verify_proof(proof).await?; self.verify_proof(proof).await?;
} }