kaspa-txscript 2.1.0

Kaspa txscript engine library
Documentation
mod error;
mod fields;
pub mod groth16;
pub mod risc0;
pub mod tags;
pub mod tests;
use crate::{
    data_stack::Stack,
    runtime_resource_meter::RuntimeResourceMeter,
    zk_precompiles::{error::ZkIntegrityError, groth16::Groth16Precompile, risc0::R0SuccinctPrecompile, tags::ZkTag},
};
use kaspa_consensus_core::mass::ScriptUnits;
use kaspa_txscript_errors::TxScriptError;

trait ZkPrecompile {
    type Error: Into<ZkIntegrityError> + std::fmt::Display;
    fn verify_zk(dstack: &mut Stack, meter: &mut RuntimeResourceMeter) -> Result<(), Self::Error>;
}

pub(crate) fn parse_tag(dstack: &mut Stack) -> Result<ZkTag, TxScriptError> {
    let tag_bytes = dstack.pop()?;
    match tag_bytes.as_slice() {
        [tag_byte] => ZkTag::try_from(*tag_byte).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
        [] => Err(TxScriptError::ZkIntegrity("Tag byte is missing".to_string())),
        _ => Err(TxScriptError::ZkIntegrity(format!("Tag byte length {} is invalid", tag_bytes.len()))),
    }
}

/**
 * Verifies a ZK proof from the data stack.
 * The first byte on the stack indicates the ZK tag (proof type).
 */
pub(crate) fn verify_zk(tag: ZkTag, dstack: &mut Stack, meter: &mut RuntimeResourceMeter) -> Result<(), TxScriptError> {
    // Match the tag and verify the proof accordingly
    match tag {
        ZkTag::Groth16 => Groth16Precompile::verify_zk(dstack, meter).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
        ZkTag::R0Succinct => R0SuccinctPrecompile::verify_zk(dstack, meter).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
    }
}

/**
 * A helper function to compute the cost (in script units) of a ZK proof based on its tag.
 */
pub fn compute_zk_cost(tag: u8) -> ScriptUnits {
    ZkTag::try_from(tag).map(|t| t.cost()).unwrap_or(ZkTag::max_cost()) // Default to max cost for unknown tags
}