Skip to main content

tidecoin_consensus_core/
verify.rs

1//! Shared typed verification facade over the Tidecoin interpreter.
2
3use crate::{
4    Interpreter, ScriptError, ScriptFlags, SpendContext, TidecoinValidationError,
5    TransactionContext, VERIFY_CLEANSTACK, VERIFY_P2SH, VERIFY_WITNESS,
6};
7use primitives::Transaction;
8
9/// Detailed failure information for a typed verification call.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct VerificationFailure {
12    /// High-level verification error.
13    pub error: TidecoinValidationError,
14    /// Final interpreter script error.
15    pub script_error: ScriptError,
16}
17
18/// Verifies a single typed spend and returns the shared-core validation error.
19pub fn verify_script_input(
20    tx: &Transaction,
21    input_index: usize,
22    spend: SpendContext<'_>,
23    flags: u32,
24) -> Result<(), TidecoinValidationError> {
25    verify_script_input_detailed(tx, input_index, spend, flags).map_err(|failure| failure.error)
26}
27
28/// Validates raw verification bits against the shared Tidecoin engine contract.
29pub fn validate_verification_flags(flags: u32) -> Result<(), TidecoinValidationError> {
30    let _ = ScriptFlags::from_bits(normalize_flags(flags))?;
31    Ok(())
32}
33
34/// Same as [`verify_script_input`] but also reports the final interpreter script error.
35pub fn verify_script_input_detailed(
36    tx: &Transaction,
37    input_index: usize,
38    spend: SpendContext<'_>,
39    flags: u32,
40) -> Result<(), VerificationFailure> {
41    let flags = ScriptFlags::from_bits(normalize_flags(flags)).map_err(simple_failure)?;
42    let tx_ctx = TransactionContext::new(tx);
43    let mut interpreter =
44        Interpreter::new(&tx_ctx, input_index, spend, flags).map_err(simple_failure)?;
45
46    interpreter.verify().map_err(|err| {
47        let script_error = interpreter.last_script_error();
48        VerificationFailure { error: normalize_script_error(err, script_error), script_error }
49    })
50}
51
52fn normalize_flags(mut flags: u32) -> u32 {
53    if flags & VERIFY_CLEANSTACK != 0 {
54        flags |= VERIFY_P2SH | VERIFY_WITNESS;
55    }
56    flags
57}
58
59fn simple_failure(error: TidecoinValidationError) -> VerificationFailure {
60    VerificationFailure { error, script_error: ScriptError::Ok }
61}
62
63fn normalize_script_error(
64    error: TidecoinValidationError,
65    script_error: ScriptError,
66) -> TidecoinValidationError {
67    match error {
68        TidecoinValidationError::Script(_) => TidecoinValidationError::Script(script_error),
69        other => other,
70    }
71}