use std::{future::Future, pin::Pin, sync::Arc};
use tracing::Instrument;
use zebra_chain::transparent;
use zebra_script::CachedFfiTransaction;
use crate::BoxError;
#[cfg(test)]
mod tests;
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
pub struct Verifier;
#[derive(Debug)]
pub struct Request {
pub cached_ffi_transaction: Arc<CachedFfiTransaction>,
pub input_index: usize,
}
impl tower::Service<Request> for Verifier {
type Response = ();
type Error = BoxError;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
fn poll_ready(
&mut self,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
std::task::Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request) -> Self::Future {
use futures_util::FutureExt;
let Request {
cached_ffi_transaction,
input_index,
} = req;
let span = tracing::trace_span!("script");
async move {
let input = &cached_ffi_transaction
.inputs()
.get(input_index)
.ok_or_else(|| {
format!("cached_ffi_transaction missing input at index {input_index}")
})?;
match input {
transparent::Input::PrevOut { outpoint, .. } => {
let outpoint = *outpoint;
cached_ffi_transaction.is_valid(input_index)?;
tracing::trace!(?outpoint, "script verification succeeded");
Ok(())
}
transparent::Input::Coinbase { .. } => Err("unexpected coinbase input".into()),
}
}
.instrument(span)
.boxed()
}
}