zebra_consensus/
script.rs1use std::{future::Future, pin::Pin, sync::Arc};
2
3use tracing::Instrument;
4
5use zebra_chain::transparent;
6use zebra_script::CachedFfiTransaction;
7
8use crate::BoxError;
9
10#[cfg(test)]
11mod tests;
12
13#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
25pub struct Verifier;
26
27#[derive(Debug)]
29pub struct Request {
30 pub cached_ffi_transaction: Arc<CachedFfiTransaction>,
32 pub input_index: usize,
36}
37
38impl tower::Service<Request> for Verifier {
39 type Response = ();
40 type Error = BoxError;
41 type Future =
42 Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
43
44 fn poll_ready(
45 &mut self,
46 _cx: &mut std::task::Context<'_>,
47 ) -> std::task::Poll<Result<(), Self::Error>> {
48 std::task::Poll::Ready(Ok(()))
49 }
50
51 fn call(&mut self, req: Request) -> Self::Future {
52 use futures_util::FutureExt;
53
54 let Request {
55 cached_ffi_transaction,
56 input_index,
57 } = req;
58
59 let span = tracing::trace_span!("script");
60 async move {
61 let input = &cached_ffi_transaction
62 .inputs()
63 .get(input_index)
64 .ok_or_else(|| {
65 format!("cached_ffi_transaction missing input at index {input_index}")
66 })?;
67
68 match input {
69 transparent::Input::PrevOut { outpoint, .. } => {
70 let outpoint = *outpoint;
71
72 cached_ffi_transaction.is_valid(input_index)?;
74 tracing::trace!(?outpoint, "script verification succeeded");
75
76 Ok(())
77 }
78 transparent::Input::Coinbase { .. } => Err("unexpected coinbase input".into()),
79 }
80 }
81 .instrument(span)
82 .boxed()
83 }
84}