chik_sdk_types/
load_klvm.rs1use std::{collections::HashMap, fs, io, path::Path, rc::Rc};
2
3use klvm_tools_rs::{
4 classic::klvm_tools::klvmc::compile_klvm_text,
5 compiler::{compiler::DefaultCompilerOpts, comptypes::CompilerOpts},
6};
7use klvm_utils::{tree_hash, TreeHash};
8use klvmr::{serde::node_to_bytes, Allocator};
9use thiserror::Error;
10
11#[derive(Debug, Error)]
12pub enum LoadKlvmError {
13 #[error("IO error: {0}")]
14 Io(#[from] io::Error),
15
16 #[error("Invalid file name")]
17 InvalidFileName,
18
19 #[error("Compiler error: {0}")]
20 Compiler(String),
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct Compilation {
25 pub reveal: Vec<u8>,
26 pub hash: TreeHash,
27}
28
29pub fn load_klvm<P: AsRef<Path>>(
30 path: P,
31 include_paths: &[String],
32) -> Result<Compilation, LoadKlvmError> {
33 let path = path.as_ref();
34
35 let mut allocator = Allocator::new();
36
37 let opts = Rc::new(DefaultCompilerOpts::new(
38 path.file_name()
39 .ok_or(LoadKlvmError::InvalidFileName)?
40 .to_str()
41 .ok_or(LoadKlvmError::InvalidFileName)?,
42 ))
43 .set_search_paths(include_paths);
44
45 let text = fs::read_to_string(path)?;
46
47 let ptr = compile_klvm_text(
48 &mut allocator,
49 opts,
50 &mut HashMap::new(),
51 &text,
52 path.to_str().ok_or(LoadKlvmError::InvalidFileName)?,
53 false,
54 )
55 .map_err(|error| LoadKlvmError::Compiler(format!("{error:?}")))?;
56
57 let hash = tree_hash(&allocator, ptr);
58 let reveal = node_to_bytes(&allocator, ptr)?;
59
60 Ok(Compilation { reveal, hash })
61}
62
63#[cfg(test)]
64mod tests {
65 use std::borrow::Cow;
66
67 use klvm_traits::{FromKlvm, ToKlvm};
68 use klvm_utils::CurriedProgram;
69 use klvmr::{serde::node_from_bytes, NodePtr};
70 use once_cell::sync::Lazy;
71
72 use crate::{run_puzzle, Mod};
73
74 use super::*;
75
76 #[test]
77 fn test_load_klvm() -> anyhow::Result<()> {
78 #[derive(Debug, Clone, PartialEq, Eq, Hash, ToKlvm, FromKlvm)]
79 #[klvm(curry)]
80 struct TestArgs {
81 a: u64,
82 b: u64,
83 }
84
85 static TEST_MOD: Lazy<Compilation> = Lazy::new(|| {
86 load_klvm(
87 "load_klvm_test.clsp",
88 &[".".to_string(), "include".to_string()],
89 )
90 .unwrap()
91 });
92
93 impl Mod for TestArgs {
94 fn mod_reveal() -> Cow<'static, [u8]> {
95 Cow::Owned(TEST_MOD.reveal.clone())
96 }
97
98 fn mod_hash() -> TreeHash {
99 TEST_MOD.hash
100 }
101 }
102
103 let args = TestArgs { a: 10, b: 20 };
104
105 let mut allocator = Allocator::new();
106
107 let mod_ptr = node_from_bytes(&mut allocator, TestArgs::mod_reveal().as_ref())?;
108
109 let ptr = CurriedProgram {
110 program: mod_ptr,
111 args,
112 }
113 .to_klvm(&mut allocator)?;
114
115 let output = run_puzzle(&mut allocator, ptr, NodePtr::NIL)?;
116
117 assert_eq!(hex::encode(node_to_bytes(&allocator, output)?), "8200e6");
118
119 Ok(())
120 }
121}