Skip to main content

kaspa_txscript/zk_precompiles/
mod.rs

1mod error;
2mod fields;
3pub mod groth16;
4pub mod risc0;
5pub mod tags;
6pub mod tests;
7use crate::{
8    data_stack::Stack,
9    runtime_resource_meter::RuntimeResourceMeter,
10    zk_precompiles::{error::ZkIntegrityError, groth16::Groth16Precompile, risc0::R0SuccinctPrecompile, tags::ZkTag},
11};
12use kaspa_consensus_core::mass::ScriptUnits;
13use kaspa_txscript_errors::TxScriptError;
14
15trait ZkPrecompile {
16    type Error: Into<ZkIntegrityError> + std::fmt::Display;
17    fn verify_zk(dstack: &mut Stack, meter: &mut RuntimeResourceMeter) -> Result<(), Self::Error>;
18}
19
20pub(crate) fn parse_tag(dstack: &mut Stack) -> Result<ZkTag, TxScriptError> {
21    let tag_bytes = dstack.pop()?;
22    match tag_bytes.as_slice() {
23        [tag_byte] => ZkTag::try_from(*tag_byte).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
24        [] => Err(TxScriptError::ZkIntegrity("Tag byte is missing".to_string())),
25        _ => Err(TxScriptError::ZkIntegrity(format!("Tag byte length {} is invalid", tag_bytes.len()))),
26    }
27}
28
29/**
30 * Verifies a ZK proof from the data stack.
31 * The first byte on the stack indicates the ZK tag (proof type).
32 */
33pub(crate) fn verify_zk(tag: ZkTag, dstack: &mut Stack, meter: &mut RuntimeResourceMeter) -> Result<(), TxScriptError> {
34    // Match the tag and verify the proof accordingly
35    match tag {
36        ZkTag::Groth16 => Groth16Precompile::verify_zk(dstack, meter).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
37        ZkTag::R0Succinct => R0SuccinctPrecompile::verify_zk(dstack, meter).map_err(|e| TxScriptError::ZkIntegrity(e.to_string())),
38    }
39}
40
41/**
42 * A helper function to compute the cost (in script units) of a ZK proof based on its tag.
43 */
44pub fn compute_zk_cost(tag: u8) -> ScriptUnits {
45    ZkTag::try_from(tag).map(|t| t.cost()).unwrap_or(ZkTag::max_cost()) // Default to max cost for unknown tags
46}