use crate::{Prefix, Said};
use async_trait::async_trait;
use super::error::WitnessError;
use super::hash::EventHash;
use super::receipt::{Receipt, SignedReceipt};
#[async_trait]
pub trait AsyncWitnessProvider: Send + Sync {
async fn submit_event(
&self,
prefix: &Prefix,
event_json: &[u8],
) -> Result<SignedReceipt, WitnessError>;
async fn observe_identity_head(
&self,
prefix: &Prefix,
) -> Result<Option<EventHash>, WitnessError>;
async fn get_receipt(
&self,
prefix: &Prefix,
event_said: &Said,
) -> Result<Option<Receipt>, WitnessError>;
async fn witness_aid(&self) -> Result<Prefix, WitnessError> {
Err(WitnessError::Rejected {
reason: "witness_aid resolution not supported by this provider".to_string(),
})
}
fn quorum(&self) -> usize {
1
}
fn timeout_ms(&self) -> u64 {
5000
}
async fn is_available(&self) -> Result<bool, WitnessError> {
Ok(true)
}
}
#[derive(Debug, Clone, Default)]
pub struct NoOpAsyncWitness;
#[async_trait]
impl AsyncWitnessProvider for NoOpAsyncWitness {
async fn submit_event(
&self,
_prefix: &Prefix,
_event_json: &[u8],
) -> Result<SignedReceipt, WitnessError> {
Ok(SignedReceipt {
receipt: Receipt {
v: crate::VersionString::placeholder(),
t: super::receipt::ReceiptTag,
d: Said::new_unchecked("ENoop".into()),
i: Prefix::new_unchecked("did:key:noop".into()),
s: crate::KeriSequence::new(0),
},
signature: Vec::new(),
})
}
async fn observe_identity_head(
&self,
_prefix: &Prefix,
) -> Result<Option<EventHash>, WitnessError> {
Ok(None)
}
async fn get_receipt(
&self,
_prefix: &Prefix,
_event_said: &Said,
) -> Result<Option<Receipt>, WitnessError> {
Ok(None)
}
fn quorum(&self) -> usize {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn noop_witness_submit_returns_dummy_receipt() {
let witness = NoOpAsyncWitness;
let prefix = Prefix::new_unchecked("ETest".into());
let signed = witness.submit_event(&prefix, b"{}").await.unwrap();
assert_eq!(signed.receipt.t, "rct");
assert!(signed.signature.is_empty());
}
#[tokio::test]
async fn noop_witness_observe_returns_none() {
let witness = NoOpAsyncWitness;
let prefix = Prefix::new_unchecked("ETest".into());
let head = witness.observe_identity_head(&prefix).await.unwrap();
assert!(head.is_none());
}
#[tokio::test]
async fn noop_witness_get_receipt_returns_none() {
let witness = NoOpAsyncWitness;
let prefix = Prefix::new_unchecked("ETest".into());
let said = Said::new_unchecked("ESAID".into());
let receipt = witness.get_receipt(&prefix, &said).await.unwrap();
assert!(receipt.is_none());
}
#[tokio::test]
async fn noop_witness_quorum_is_zero() {
let witness = NoOpAsyncWitness;
assert_eq!(witness.quorum(), 0);
}
#[tokio::test]
async fn noop_witness_is_available() {
let witness = NoOpAsyncWitness;
assert!(witness.is_available().await.unwrap());
}
#[test]
fn default_timeout() {
let witness = NoOpAsyncWitness;
assert_eq!(witness.timeout_ms(), 5000);
}
}