ckb_debugger/
api.rs

1use ckb_chain_spec::consensus::ConsensusBuilder;
2use ckb_mock_tx_types::{MockTransaction, ReprMockTransaction, Resource};
3use ckb_script::{ScriptGroupType, TransactionScriptsVerifier, TxVerifyEnv};
4use ckb_types::{
5    core::cell::resolve_transaction,
6    core::hardfork::{CKB2021, CKB2023, HardForks},
7    core::{Cycle, EpochNumberWithFraction, HeaderView},
8    packed::Byte32,
9    prelude::*,
10};
11use serde::{Deserialize, Serialize};
12use std::collections::HashSet;
13use std::sync::Arc;
14use wasm_bindgen::prelude::*;
15
16pub fn run(
17    mock_tx: &MockTransaction,
18    script_group_type: &ScriptGroupType,
19    script_hash: &Byte32,
20    max_cycle: Cycle,
21) -> Result<Cycle, Box<dyn std::error::Error>> {
22    let resource = Resource::from_mock_tx(mock_tx)?;
23    let resolve_transaction =
24        resolve_transaction(mock_tx.core_transaction(), &mut HashSet::new(), &resource, &resource)?;
25    let hardforks = HardForks { ckb2021: CKB2021::new_dev_default(), ckb2023: CKB2023::new_dev_default() };
26    let consensus = Arc::new(ConsensusBuilder::default().hardfork_switch(hardforks).build());
27    let epoch = EpochNumberWithFraction::new(0, 0, 1);
28    let header = HeaderView::new_advanced_builder().epoch(epoch.pack()).build();
29    let tx_env = Arc::new(TxVerifyEnv::new_commit(&header));
30    let mut verifier = TransactionScriptsVerifier::new(
31        Arc::new(resolve_transaction),
32        resource.clone(),
33        consensus.clone(),
34        tx_env.clone(),
35    );
36    verifier.set_debug_printer(Box::new(move |_hash: &Byte32, message: &str| {
37        let message = message.trim_end_matches('\n');
38        if message != "" {
39            crate::arch::println(&format!("Script log: {}", message));
40        }
41    }));
42    Ok(verifier.verify_single(*script_group_type, script_hash, max_cycle)?)
43}
44
45#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug)]
46struct JsonResult {
47    cycle: Option<Cycle>,
48    error: Option<String>,
49}
50
51impl From<Result<Cycle, String>> for JsonResult {
52    fn from(result: Result<Cycle, String>) -> JsonResult {
53        match result {
54            Ok(cycle) => JsonResult { cycle: Some(cycle), error: None },
55            Err(error) => JsonResult { cycle: None, error: Some(error) },
56        }
57    }
58}
59
60#[wasm_bindgen]
61pub fn run_json(mock_tx: &str, script_group_type: &str, script_hash: &str, max_cycle: &str) -> String {
62    let result = || -> Result<Cycle, String> {
63        let repr_mock_tx: ReprMockTransaction = serde_json::from_str(mock_tx).map_err(|e| e.to_string())?;
64        let mock_tx: MockTransaction = repr_mock_tx.into();
65        let script_group_type: ScriptGroupType = serde_plain::from_str(script_group_type).map_err(|e| e.to_string())?;
66        let script_hash = if script_hash.starts_with("0x") { &script_hash[2..] } else { &script_hash[0..] };
67        let script_hash_byte = hex::decode(&script_hash.as_bytes()).map_err(|e| e.to_string())?;
68        let script_hash = Byte32::from_slice(script_hash_byte.as_slice()).map_err(|e| e.to_string())?;
69        let max_cycle: Cycle = max_cycle.parse().map_err(|_| "Invalid max cycle!".to_string())?;
70        run(&mock_tx, &script_group_type, &script_hash, max_cycle).map_err(|e| e.to_string())
71    }();
72    let result_json: JsonResult = result.into();
73    serde_json::to_string(&result_json).unwrap()
74}