use std::string::ToString;
use std::vec::Vec;
use miden_client::account::AccountId;
use miden_client::block::AccountWitness;
use miden_client::store::StoreError;
use miden_client::utils::{Deserializable, Serializable};
use rusqlite::{Connection, OptionalExtension, Transaction, params};
use crate::sql_error::SqlResultExt;
use crate::{SqliteStore, insert_sql, proto, subst};
impl SqliteStore {
pub(crate) fn track_account_witness(
conn: &mut Connection,
account_id: AccountId,
) -> Result<bool, StoreError> {
const QUERY: &str = insert_sql!(account_witnesses { account_id } | IGNORE);
let inserted = conn
.prepare_cached(QUERY)
.into_store_error()?
.execute(params![account_id.to_bytes()])
.into_store_error()?;
Ok(inserted > 0)
}
pub(crate) fn untrack_account_witness(
conn: &mut Connection,
account_id: AccountId,
) -> Result<bool, StoreError> {
const QUERY: &str = "DELETE FROM account_witnesses WHERE account_id = ?";
let removed = conn
.prepare_cached(QUERY)
.into_store_error()?
.execute(params![account_id.to_bytes()])
.into_store_error()?;
Ok(removed > 0)
}
pub(crate) fn tracked_account_witnesses(
conn: &mut Connection,
) -> Result<Vec<AccountId>, StoreError> {
const QUERY: &str = "SELECT account_id FROM account_witnesses";
conn.prepare_cached(QUERY)
.into_store_error()?
.query_map([], |row| row.get(0))
.expect("no binding parameters used in query")
.map(|result| {
let id: Vec<u8> =
result.map_err(|err| StoreError::ParsingError(err.to_string()))?;
AccountId::read_from_bytes(&id).map_err(StoreError::DataDeserializationError)
})
.collect()
}
pub(crate) fn get_account_witness(
conn: &mut Connection,
account_id: AccountId,
) -> Result<Option<AccountWitness>, StoreError> {
const QUERY: &str = "SELECT witness FROM account_witnesses \
WHERE account_id = ? AND witness IS NOT NULL";
let witness: Option<Vec<u8>> = conn
.prepare_cached(QUERY)
.into_store_error()?
.query_row(params![account_id.to_bytes()], |row| row.get(0))
.optional()
.into_store_error()?;
Ok(witness.map(|witness| proto::decode_unchecked(&witness)).transpose()?)
}
pub(crate) fn update_account_witness(
conn: &mut Connection,
account_id: AccountId,
witness: &AccountWitness,
) -> Result<bool, StoreError> {
let tx = conn.transaction().into_store_error()?;
let updated = Self::update_account_witness_tx(&tx, account_id, witness)?;
tx.commit().into_store_error()?;
Ok(updated)
}
pub(crate) fn update_account_witness_tx(
tx: &Transaction<'_>,
account_id: AccountId,
witness: &AccountWitness,
) -> Result<bool, StoreError> {
const QUERY: &str = "UPDATE account_witnesses SET witness = ? WHERE account_id = ?";
let updated = tx
.prepare_cached(QUERY)
.into_store_error()?
.execute(params![proto::encode(witness), account_id.to_bytes()])
.into_store_error()?;
Ok(updated > 0)
}
}