Prepared Send (#596)

Co-authored-by: thesimplekid <tsk@thesimplekid.com>
Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
This commit is contained in:
David Caseria
2025-03-20 07:44:44 -04:00
committed by GitHub
parent c4488ce436
commit db1db86509
24 changed files with 1179 additions and 460 deletions

View File

@@ -0,0 +1,31 @@
-- Create a new table with the updated CHECK constraint
CREATE TABLE IF NOT EXISTS proof_new (
y BLOB PRIMARY KEY,
mint_url TEXT NOT NULL,
state TEXT CHECK ( state IN ('SPENT', 'UNSPENT', 'PENDING', 'RESERVED', 'PENDING_SPENT' ) ) NOT NULL,
spending_condition TEXT,
unit TEXT NOT NULL,
amount INTEGER NOT NULL,
keyset_id TEXT NOT NULL,
secret TEXT NOT NULL,
c BLOB NOT NULL,
witness TEXT
);
CREATE INDEX IF NOT EXISTS secret_index ON proof_new(secret);
CREATE INDEX IF NOT EXISTS state_index ON proof_new(state);
CREATE INDEX IF NOT EXISTS spending_condition_index ON proof_new(spending_condition);
CREATE INDEX IF NOT EXISTS unit_index ON proof_new(unit);
CREATE INDEX IF NOT EXISTS amount_index ON proof_new(amount);
CREATE INDEX IF NOT EXISTS mint_url_index ON proof_new(mint_url);
-- Copy data from old proof table to new proof table
INSERT INTO proof_new (y, mint_url, state, spending_condition, unit, amount, keyset_id, secret, c, witness)
SELECT y, mint_url, state, spending_condition, unit, amount, keyset_id, secret, c, witness
FROM proof;
-- Drop the old proof table
DROP TABLE proof;
-- Rename the new proof table to proof
ALTER TABLE proof_new RENAME TO proof;

View File

@@ -59,23 +59,6 @@ impl WalletSqliteDatabase {
.await
.expect("Could not run migrations");
}
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), database::Error> {
sqlx::query(
r#"
UPDATE proof
SET state=?
WHERE y IS ?;
"#,
)
.bind(state.to_string())
.bind(y.to_bytes().to_vec())
.execute(&self.pool)
.await
.map_err(Error::from)?;
Ok(())
}
}
#[async_trait]
@@ -658,30 +641,6 @@ WHERE id=?
Ok(())
}
async fn set_pending_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Pending).await?;
}
Ok(())
}
async fn reserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Reserved).await?;
}
Ok(())
}
async fn set_unspent_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Unspent).await?;
}
Ok(())
}
#[instrument(skip(self, state, spending_conditions))]
async fn get_proofs(
&self,
@@ -734,6 +693,31 @@ FROM proof;
}
}
async fn update_proofs_state(&self, ys: Vec<PublicKey>, state: State) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let update_sql = format!(
"UPDATE proof SET state = ? WHERE y IN ({})",
"?,".repeat(ys.len()).trim_end_matches(',')
);
ys.iter()
.fold(
sqlx::query(&update_sql).bind(state.to_string()),
|query, y| query.bind(y.to_bytes().to_vec()),
)
.execute(&mut *transaction)
.await
.map_err(|err| {
tracing::error!("SQLite could not update proof state: {err:?}");
Error::SQLX(err)
})?;
transaction.commit().await.map_err(Error::from)?;
Ok(())
}
#[instrument(skip(self), fields(keyset_id = %keyset_id))]
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;