use crate::models::dht::WarrantRow;
use holo_hash::{AgentPubKey, DhtOpHash};
use holochain_timestamp::Timestamp;
use sqlx::{Executor, Sqlite, SqliteConnection};
pub struct InsertWarrant<'a> {
pub hash: &'a DhtOpHash,
pub author: &'a AgentPubKey,
pub timestamp: Timestamp,
pub warrantee: &'a AgentPubKey,
pub proof: &'a [u8],
pub signature: &'a [u8],
pub reason: Option<&'a str>,
pub storage_center_loc: u32,
pub when_received: Timestamp,
pub when_integrated: Timestamp,
pub validation_status: i64,
pub serialized_size: u32,
}
pub(crate) async fn insert_warrant<'a>(
conn: &mut SqliteConnection,
w: InsertWarrant<'a>,
) -> sqlx::Result<()> {
sqlx::query(
"INSERT INTO Warrant (hash, author, timestamp, warrantee, proof, signature, reason)
VALUES (?, ?, ?, ?, ?, ?, ?)",
)
.bind(w.hash.get_raw_36())
.bind(w.author.get_raw_36())
.bind(w.timestamp.as_micros())
.bind(w.warrantee.get_raw_36())
.bind(w.proof)
.bind(w.signature)
.bind(w.reason)
.execute(&mut *conn)
.await?;
sqlx::query(
"INSERT INTO WarrantOp (hash, storage_center_loc, when_received,
when_integrated, validation_status, serialized_size)
VALUES (?, ?, ?, ?, ?, ?)",
)
.bind(w.hash.get_raw_36())
.bind(w.storage_center_loc as i64)
.bind(w.when_received.as_micros())
.bind(w.when_integrated.as_micros())
.bind(w.validation_status)
.bind(w.serialized_size as i64)
.execute(&mut *conn)
.await?;
Ok(())
}
pub(crate) async fn pending_or_valid_warrant_proofs_by_warrantee<'e, E>(
executor: E,
warrantee: &AgentPubKey,
) -> sqlx::Result<Vec<Vec<u8>>>
where
E: Executor<'e, Database = Sqlite>,
{
let rows: Vec<(Vec<u8>,)> = sqlx::query_as(
"SELECT w.proof
FROM Warrant w
JOIN LimboWarrantOp op ON op.hash = w.hash
WHERE w.warrantee = ?
AND op.abandoned_at IS NULL
AND (op.sys_validation_status IS NULL OR op.sys_validation_status = 1)
UNION ALL
SELECT w.proof
FROM Warrant w
JOIN WarrantOp op ON op.hash = w.hash
WHERE w.warrantee = ?
AND op.validation_status = 1",
)
.bind(warrantee.get_raw_36())
.bind(warrantee.get_raw_36())
.fetch_all(executor)
.await?;
Ok(rows.into_iter().map(|(proof,)| proof).collect())
}
pub(crate) async fn get_warrant<'e, E>(
executor: E,
hash: DhtOpHash,
) -> sqlx::Result<Option<WarrantRow>>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_as(
"SELECT w.hash, w.author, w.timestamp, w.warrantee, w.proof, w.signature, w.reason,
op.storage_center_loc, op.when_received, op.when_integrated,
op.serialized_size
FROM Warrant w
JOIN WarrantOp op ON op.hash = w.hash
WHERE w.hash = ?",
)
.bind(hash.get_raw_36())
.fetch_optional(executor)
.await
}
pub(crate) async fn get_warrants_by_warrantee<'e, E>(
executor: E,
warrantee: AgentPubKey,
) -> sqlx::Result<Vec<WarrantRow>>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_as(
"SELECT w.hash, w.author, w.timestamp, w.warrantee, w.proof, w.signature, w.reason,
op.storage_center_loc, op.when_received, op.when_integrated,
op.serialized_size
FROM Warrant w
JOIN WarrantOp op ON op.hash = w.hash
WHERE w.warrantee = ?
ORDER BY w.timestamp DESC",
)
.bind(warrantee.get_raw_36())
.fetch_all(executor)
.await
}
pub(crate) async fn get_warrants_by_author<'e, E>(
executor: E,
author: AgentPubKey,
) -> sqlx::Result<Vec<WarrantRow>>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_as(
"SELECT w.hash, w.author, w.timestamp, w.warrantee, w.proof, w.signature, w.reason,
COALESCE(op.storage_center_loc, lop.storage_center_loc) AS storage_center_loc,
COALESCE(op.when_received, lop.when_received) AS when_received,
COALESCE(op.when_integrated, 0) AS when_integrated,
COALESCE(op.serialized_size, lop.serialized_size) AS serialized_size
FROM Warrant w
LEFT JOIN WarrantOp op ON op.hash = w.hash
LEFT JOIN LimboWarrantOp lop ON lop.hash = w.hash
WHERE w.author = ? AND (op.hash IS NOT NULL OR lop.hash IS NOT NULL)
ORDER BY w.timestamp DESC",
)
.bind(author.get_raw_36())
.fetch_all(executor)
.await
}
pub(crate) async fn warrant_op_validation_status<'e, E>(
executor: E,
op_hash: &DhtOpHash,
) -> sqlx::Result<Option<i64>>
where
E: Executor<'e, Database = Sqlite>,
{
let hash = op_hash.get_raw_36().to_vec();
let (status,): (Option<i64>,) = sqlx::query_as(
"SELECT COALESCE(
(SELECT validation_status FROM WarrantOp WHERE hash = ?),
(SELECT sys_validation_status FROM LimboWarrantOp WHERE hash = ?)
)",
)
.bind(hash.clone())
.bind(hash)
.fetch_one(executor)
.await?;
Ok(status)
}