use std::future::Future;
use std::pin::Pin;
use tokio::sync::Mutex;
use vta_sdk::sealed_transfer::{NonceStore, SealedTransferError};
use crate::store::KeyspaceHandle;
const KEY_PREFIX: &str = "sealed-nonce:";
pub struct PersistentNonceStore {
ks: KeyspaceHandle,
lock: Mutex<()>,
}
impl PersistentNonceStore {
pub fn new(ks: KeyspaceHandle) -> Self {
Self {
ks,
lock: Mutex::new(()),
}
}
fn key(bundle_id: &[u8; 16]) -> String {
let mut s = String::with_capacity(KEY_PREFIX.len() + 32);
s.push_str(KEY_PREFIX);
const T: &[u8; 16] = b"0123456789abcdef";
for &b in bundle_id {
s.push(T[(b >> 4) as usize] as char);
s.push(T[(b & 0xf) as usize] as char);
}
s
}
}
impl NonceStore for PersistentNonceStore {
fn check_and_record<'a>(
&'a self,
bundle_id: &'a [u8; 16],
) -> Pin<Box<dyn Future<Output = Result<(), SealedTransferError>> + Send + 'a>> {
let key = Self::key(bundle_id);
Box::pin(async move {
let _guard = self.lock.lock().await;
if self
.ks
.get_raw(key.clone())
.await
.map_err(|e| SealedTransferError::NonceStore(e.to_string()))?
.is_some()
{
return Err(SealedTransferError::NonceReplay);
}
self.ks
.insert_raw(key, b"1".to_vec())
.await
.map_err(|e| SealedTransferError::NonceStore(e.to_string()))?;
Ok(())
})
}
}