simplicity/jet/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! # Simplicity jets
4//!
5//! Jets are special nodes that read a value,
6//! process it internally, and write an output value.
7//! This evaluation happens in a black-box manner:
8//! In terms of the Bit Machine, it is a one-step process.
9//!
10//! In practice, jets call foreign C code that is equivalent to some Simplicity DAG.
11//! This speeds up evaluation tremendously.
12//! Equivalence of C and Simplicity is proved using the _Verified Software Toolchain_.
13//! Programs are also smaller in size because jets replace large, equivalent Simplicity DAGs.
14
15#[cfg(feature = "bitcoin")]
16pub mod bitcoin;
17#[cfg(feature = "elements")]
18pub mod elements;
19mod init;
20pub mod type_name;
21
22#[cfg(feature = "bitcoin")]
23pub use init::bitcoin::Bitcoin;
24pub use init::core::Core;
25#[cfg(feature = "elements")]
26pub use init::elements::Elements;
27use simplicity_sys::c_jets::frame_ffi::CFrameItem;
28
29use crate::analysis::Cost;
30use crate::decode;
31use crate::jet::type_name::TypeName;
32use crate::merkle::cmr::Cmr;
33use crate::{BitIter, BitWriter};
34use std::hash::Hash;
35use std::io::Write;
36
37/// Generic error that a jet failed during its execution.
38///
39/// Failure could be due to a failed assertion, an illegal input, etc.
40#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
41pub struct JetFailed;
42
43impl std::fmt::Display for JetFailed {
44    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
45        f.write_str("Jet failed during execution")
46    }
47}
48
49impl std::error::Error for JetFailed {}
50
51/// Family of jets that share an encoding scheme and execution environment.
52///
53/// Jets are single nodes that read an input,
54/// process it internally using foreign C code _(black box)_,
55/// and produce an output.
56/// Jets may read values from their _environment_.
57///
58/// Jets are **always** leaves in a Simplicity DAG.
59pub trait Jet:
60    Copy + Eq + Ord + Hash + std::fmt::Debug + std::fmt::Display + std::str::FromStr + 'static
61{
62    /// Environment for jet to read from
63    type Environment;
64    /// CJetEnvironment to interact with C FFI.
65    type CJetEnvironment;
66
67    /// Return the CMR of the jet.
68    fn cmr(&self) -> Cmr;
69
70    /// Return the source type of the jet.
71    fn source_ty(&self) -> TypeName;
72
73    /// Return the target type of the jet.
74    fn target_ty(&self) -> TypeName;
75
76    /// Encode the jet to bits.
77    fn encode<W: Write>(&self, w: &mut BitWriter<W>) -> std::io::Result<usize>;
78
79    /// Decode a jet from bits.
80    fn decode<I: Iterator<Item = u8>>(bits: &mut BitIter<I>) -> Result<Self, decode::Error>;
81
82    /// Obtains a C FFI compatible environment for the jet.
83    fn c_jet_env(env: &Self::Environment) -> &Self::CJetEnvironment;
84
85    /// Obtain the FFI C pointer for the jet.
86    fn c_jet_ptr(&self) -> &dyn Fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool;
87
88    /// Return the cost of the jet.
89    fn cost(&self) -> Cost;
90}
91
92#[cfg(test)]
93mod tests {
94    use crate::jet::Core;
95    use crate::node::{ConstructNode, CoreConstructible, JetConstructible};
96    use crate::types;
97    use crate::value::Word;
98    use crate::{BitMachine, Value};
99    use std::sync::Arc;
100
101    #[test]
102    fn test_ffi_jet() {
103        types::Context::with_context(|ctx| {
104            let two_words = Arc::<ConstructNode<_>>::comp(
105                &Arc::<ConstructNode<_>>::pair(
106                    &Arc::<ConstructNode<_>>::const_word(&ctx, Word::u32(2)),
107                    &Arc::<ConstructNode<_>>::const_word(&ctx, Word::u32(16)),
108                )
109                .unwrap(),
110                &Arc::<ConstructNode<_>>::jet(&ctx, Core::Add32),
111            )
112            .unwrap();
113            assert_eq!(
114                BitMachine::test_exec(two_words, &()).expect("executing"),
115                Value::product(
116                    Value::u1(0),       // carry bit
117                    Value::u32(2 + 16), // result
118                ),
119            );
120        });
121    }
122
123    #[test]
124    fn test_simple() {
125        types::Context::with_context(|ctx| {
126            let two_words = Arc::<ConstructNode<Core>>::pair(
127                &Arc::<ConstructNode<_>>::const_word(&ctx, Word::u32(2)),
128                &Arc::<ConstructNode<_>>::const_word(&ctx, Word::u16(16)),
129            )
130            .unwrap();
131            assert_eq!(
132                BitMachine::test_exec(two_words, &()).expect("executing"),
133                Value::product(Value::u32(2), Value::u16(16)),
134            );
135        });
136    }
137}