1mod frame;
10mod limits;
11mod tracker;
12
13use std::error;
14use std::fmt;
15use std::sync::Arc;
16
17use crate::analysis;
18use crate::jet::{Jet, JetFailed};
19use crate::node::{self, RedeemNode};
20use crate::types::Final;
21use crate::{Cmr, FailEntropy, Value};
22use frame::Frame;
23
24pub use self::limits::LimitError;
25pub use self::tracker::{
26 ExecTracker, NoTracker, NodeOutput, PruneTracker, SetTracker, StderrTracker,
27};
28
29pub type FrameIter<'a> = crate::BitIter<core::iter::Copied<core::slice::Iter<'a, u8>>>;
31
32pub struct BitMachine {
34 data: Vec<u8>,
37 next_frame_start: usize,
39 read: Vec<Frame>,
41 write: Vec<Frame>,
43 source_ty: Arc<Final>,
45}
46
47impl BitMachine {
48 pub fn for_program<J: Jet>(program: &RedeemNode<J>) -> Result<Self, LimitError> {
50 LimitError::check_program(program)?;
51 let io_width = program.arrow().source.bit_width() + program.arrow().target.bit_width();
52
53 Ok(Self {
54 data: vec![0; (io_width + program.bounds().extra_cells).div_ceil(8)],
55 next_frame_start: 0,
56 read: Vec::with_capacity(program.bounds().extra_frames + analysis::IO_EXTRA_FRAMES),
57 write: Vec::with_capacity(program.bounds().extra_frames + analysis::IO_EXTRA_FRAMES),
58 source_ty: program.arrow().source.clone(),
59 })
60 }
61
62 #[cfg(test)]
63 pub fn test_exec<J: Jet>(
64 program: Arc<crate::node::ConstructNode<J>>,
65 env: &J::Environment,
66 ) -> Result<Value, ExecutionError> {
67 use crate::node::SimpleFinalizer;
68
69 let prog = program
70 .finalize_types_non_program()
71 .expect("finalizing types")
72 .finalize(&mut SimpleFinalizer::new(None.into_iter()))
73 .expect("finalizing");
74 let mut mac = BitMachine::for_program(&prog).expect("program has reasonable bounds");
75 mac.exec(&prog, env)
76 }
77
78 fn new_write_frame(&mut self, len: usize) {
80 debug_assert!(
81 self.next_frame_start + len <= self.data.len() * 8,
82 "Data out of bounds: number of cells"
83 );
84 debug_assert!(
85 self.write.len() + self.read.len() < self.read.capacity(),
86 "Stacks out of bounds: number of frames"
87 );
88
89 self.write.push(Frame::new(self.next_frame_start, len));
90 self.next_frame_start += len;
91 }
92
93 fn move_write_frame_to_read(&mut self) {
95 let mut _active_write_frame = self.write.pop().unwrap();
96 _active_write_frame.reset_cursor();
97 self.read.push(_active_write_frame);
98 }
99
100 fn drop_read_frame(&mut self) {
102 let active_read_frame = self.read.pop().unwrap();
103 self.next_frame_start -= active_read_frame.bit_width();
104 assert_eq!(self.next_frame_start, active_read_frame.start());
105 }
106
107 fn write_bit(&mut self, bit: bool) {
109 self.write
110 .last_mut()
111 .expect("Empty write frame stack")
112 .write_bit(bit, &mut self.data);
113 }
114
115 fn skip(&mut self, n: usize) {
118 if n == 0 {
120 return;
121 }
122 let idx = self.write.len() - 1;
123 self.write[idx].move_cursor_forward(n);
124 }
125
126 fn copy(&mut self, n: usize) {
129 if n == 0 {
131 return;
132 }
133 let widx = self.write.len() - 1;
134 let ridx = self.read.len() - 1;
135 self.write[widx].copy_from(&self.read[ridx], n, &mut self.data);
136 }
137
138 fn fwd(&mut self, n: usize) {
141 if n == 0 {
143 return;
144 }
145 let idx = self.read.len() - 1;
146 self.read[idx].move_cursor_forward(n);
147 }
148
149 fn back(&mut self, n: usize) {
152 if n == 0 {
154 return;
155 }
156 let idx = self.read.len() - 1;
157 self.read[idx].move_cursor_backward(n);
158 }
159
160 fn write_u8(&mut self, value: u8) {
162 self.write
163 .last_mut()
164 .expect("Empty write frame stack")
165 .write_u8(value, &mut self.data);
166 }
167
168 fn read_bit(&mut self) -> bool {
170 self.read
171 .last_mut()
172 .expect("Empty read frame stack")
173 .read_bit(&self.data)
174 }
175
176 fn write_bytes(&mut self, bytes: &[u8]) {
178 for bit in bytes {
179 self.write_u8(*bit);
180 }
181 }
182
183 fn write_value(&mut self, val: &Value) {
185 for bit in val.iter_padded() {
186 self.write_bit(bit);
187 }
188 }
189
190 fn active_read_bit_width(&self) -> usize {
192 self.read.last().map(|frame| frame.bit_width()).unwrap_or(0)
193 }
194
195 fn active_write_bit_width(&self) -> usize {
197 self.write
198 .last()
199 .map(|frame| frame.bit_width())
200 .unwrap_or(0)
201 }
202
203 pub fn input(&mut self, input: &Value) -> Result<(), ExecutionError> {
206 if !input.is_of_type(&self.source_ty) {
207 return Err(ExecutionError::InputWrongType(self.source_ty.clone()));
208 }
209 if !input.is_empty() {
211 self.new_write_frame(input.padded_len());
212 self.write_value(input);
213 self.move_write_frame_to_read();
214 }
215 Ok(())
216 }
217
218 pub fn exec<J: Jet>(
224 &mut self,
225 program: &RedeemNode<J>,
226 env: &J::Environment,
227 ) -> Result<Value, ExecutionError> {
228 self.exec_with_tracker(program, env, &mut NoTracker)
229 }
230
231 pub fn exec_with_tracker<J: Jet, T: ExecTracker<J>>(
240 &mut self,
241 program: &RedeemNode<J>,
242 env: &J::Environment,
243 tracker: &mut T,
244 ) -> Result<Value, ExecutionError> {
245 enum CallStack<'a, J: Jet> {
246 Goto(&'a RedeemNode<J>),
247 MoveWriteFrameToRead,
248 DropReadFrame,
249 CopyFwd(usize),
250 Back(usize),
251 }
252
253 impl<J: Jet> fmt::Debug for CallStack<'_, J> {
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 match self {
257 CallStack::Goto(ins) => write!(f, "goto {}", ins.inner()),
258 CallStack::MoveWriteFrameToRead => f.write_str("move frame"),
259 CallStack::DropReadFrame => f.write_str("drop frame"),
260 CallStack::CopyFwd(n) => write!(f, "copy/fwd {}", n),
261 CallStack::Back(n) => write!(f, "back {}", n),
262 }
263 }
264 }
265
266 if self.read.is_empty() != self.source_ty.is_empty() {
267 return Err(ExecutionError::InputWrongType(self.source_ty.clone()));
268 }
269
270 let mut ip = program;
271 let mut call_stack = vec![];
272
273 let output_width = ip.arrow().target.bit_width();
274 if output_width > 0 {
275 self.new_write_frame(output_width);
276 }
277
278 'main_loop: loop {
279 let input_frame = self.read.last().map(Frame::shallow_copy);
281 let mut jet_result = Ok(());
282
283 match ip.inner() {
284 node::Inner::Unit => {}
285 node::Inner::Iden => {
286 let size_a = ip.arrow().source.bit_width();
287 self.copy(size_a);
288 }
289 node::Inner::InjL(left) => {
290 let (b, c) = ip.arrow().target.as_sum().unwrap();
291 self.write_bit(false);
292 self.skip(b.pad_left(c));
293 call_stack.push(CallStack::Goto(left));
294 }
295 node::Inner::InjR(left) => {
296 let (b, c) = ip.arrow().target.as_sum().unwrap();
297 self.write_bit(true);
298 self.skip(b.pad_right(c));
299 call_stack.push(CallStack::Goto(left));
300 }
301 node::Inner::Pair(left, right) => {
302 call_stack.push(CallStack::Goto(right));
303 call_stack.push(CallStack::Goto(left));
304 }
305 node::Inner::Comp(left, right) => {
306 let size_b = left.arrow().target.bit_width();
307
308 self.new_write_frame(size_b);
309 call_stack.push(CallStack::DropReadFrame);
310 call_stack.push(CallStack::Goto(right));
311 call_stack.push(CallStack::MoveWriteFrameToRead);
312 call_stack.push(CallStack::Goto(left));
313 }
314 node::Inner::Disconnect(left, right) => {
315 let size_prod_256_a = left.arrow().source.bit_width();
316 let size_a = size_prod_256_a - 256;
317 let size_prod_b_c = left.arrow().target.bit_width();
318 let size_b = size_prod_b_c - right.arrow().source.bit_width();
319
320 self.new_write_frame(size_prod_256_a);
321 self.write_bytes(right.cmr().as_ref());
322 self.copy(size_a);
323 self.move_write_frame_to_read();
324 self.new_write_frame(size_prod_b_c);
325
326 call_stack.push(CallStack::DropReadFrame);
328 call_stack.push(CallStack::DropReadFrame);
329 call_stack.push(CallStack::Goto(right));
330 call_stack.push(CallStack::CopyFwd(size_b));
331 call_stack.push(CallStack::MoveWriteFrameToRead);
332 call_stack.push(CallStack::Goto(left));
333 }
334 node::Inner::Take(left) => call_stack.push(CallStack::Goto(left)),
335 node::Inner::Drop(left) => {
336 let size_a = ip.arrow().source.as_product().unwrap().0.bit_width();
337 self.fwd(size_a);
338 call_stack.push(CallStack::Back(size_a));
339 call_stack.push(CallStack::Goto(left));
340 }
341 node::Inner::Case(..) | node::Inner::AssertL(..) | node::Inner::AssertR(..) => {
342 let in_frame = &self.read[self.read.len() - 1];
343 let choice_bit: bool = in_frame.peek_bit(&self.data);
344
345 let (sum_a_b, _c) = ip.arrow().source.as_product().unwrap();
346 let (a, b) = sum_a_b.as_sum().unwrap();
347
348 match (ip.inner(), choice_bit) {
349 (node::Inner::Case(_, right), true)
350 | (node::Inner::AssertR(_, right), true) => {
351 self.fwd(1 + a.pad_right(b));
352 call_stack.push(CallStack::Back(1 + a.pad_right(b)));
353 call_stack.push(CallStack::Goto(right));
354 }
355 (node::Inner::Case(left, _), false)
356 | (node::Inner::AssertL(left, _), false) => {
357 self.fwd(1 + a.pad_left(b));
358 call_stack.push(CallStack::Back(1 + a.pad_left(b)));
359 call_stack.push(CallStack::Goto(left));
360 }
361 (node::Inner::AssertL(_, r_cmr), true) => {
362 return Err(ExecutionError::ReachedPrunedBranch(*r_cmr))
363 }
364 (node::Inner::AssertR(l_cmr, _), false) => {
365 return Err(ExecutionError::ReachedPrunedBranch(*l_cmr))
366 }
367 _ => unreachable!(),
368 }
369 }
370 node::Inner::Witness(value) => self.write_value(value),
371 node::Inner::Jet(jet) => {
372 jet_result = self.exec_jet(*jet, env);
373 }
374 node::Inner::Word(value) => self.write_value(value.as_value()),
375 node::Inner::Fail(entropy) => {
376 return Err(ExecutionError::ReachedFailNode(*entropy))
377 }
378 }
379
380 {
382 let read_iter = input_frame
388 .map(|frame| frame.as_bit_iter(&self.data))
389 .unwrap_or(crate::BitIter::from([].iter().copied()));
390 let output = match (ip.inner(), &jet_result) {
393 (node::Inner::Unit | node::Inner::Iden | node::Inner::Witness(_), _)
394 | (node::Inner::Jet(_), Ok(_)) => NodeOutput::Success(
395 self.write
396 .last()
397 .map(|r| r.as_bit_iter(&self.data))
398 .unwrap_or(crate::BitIter::from([].iter().copied())),
399 ),
400 (node::Inner::Jet(_), Err(_)) => NodeOutput::JetFailed,
401 _ => NodeOutput::NonTerminal,
402 };
403 tracker.visit_node(ip, read_iter, output);
404 }
405 jet_result?;
407
408 ip = loop {
409 match call_stack.pop() {
410 Some(CallStack::Goto(next)) => break next,
411 Some(CallStack::MoveWriteFrameToRead) => self.move_write_frame_to_read(),
412 Some(CallStack::DropReadFrame) => self.drop_read_frame(),
413 Some(CallStack::CopyFwd(n)) => {
414 self.copy(n);
415 self.fwd(n);
416 }
417 Some(CallStack::Back(n)) => self.back(n),
418 None => break 'main_loop,
419 };
420 };
421 }
422
423 if output_width > 0 {
424 let out_frame = self.write.last_mut().unwrap();
425 out_frame.reset_cursor();
426 let value = Value::from_padded_bits(
427 &mut out_frame.as_bit_iter(&self.data),
428 &program.arrow().target,
429 )
430 .expect("Decode value of output frame");
431
432 Ok(value)
433 } else {
434 Ok(Value::unit())
435 }
436 }
437
438 fn exec_jet<J: Jet>(&mut self, jet: J, env: &J::Environment) -> Result<(), JetFailed> {
439 use crate::ffi::c_jets::frame_ffi::{c_readBit, c_writeBit, CFrameItem};
440 use crate::ffi::c_jets::uword_width;
441 use crate::ffi::ffi::UWORD;
442
443 unsafe fn get_input_frame(
455 mac: &mut BitMachine,
456 bit_width: usize,
457 ) -> (CFrameItem, Vec<UWORD>) {
458 assert!(bit_width <= mac.active_read_bit_width());
459 let uword_width = uword_width(bit_width);
460 let mut buffer = vec![0; uword_width];
461
462 let buffer_end = buffer.as_mut_ptr().add(uword_width);
464 let mut write_frame = CFrameItem::new_write(bit_width, buffer_end);
465 for _ in 0..bit_width {
466 let bit = mac.read_bit();
467 c_writeBit(&mut write_frame, bit);
468 }
469 mac.back(bit_width);
470
471 let buffer_ptr = buffer.as_mut_ptr();
473 let read_frame = CFrameItem::new_read(bit_width, buffer_ptr);
474
475 (read_frame, buffer)
476 }
477
478 unsafe fn get_output_frame(bit_width: usize) -> (CFrameItem, Vec<UWORD>) {
486 let uword_width = uword_width(bit_width);
487 let mut buffer = vec![0; uword_width];
488
489 let buffer_end = buffer.as_mut_ptr().add(uword_width);
491 let write_frame = CFrameItem::new_write(bit_width, buffer_end);
492
493 (write_frame, buffer)
494 }
495
496 fn update_active_write_frame(mac: &mut BitMachine, bit_width: usize, buffer: &[UWORD]) {
504 assert!(bit_width <= mac.active_write_bit_width());
505 assert!(uword_width(bit_width) <= buffer.len());
506 let buffer_ptr = buffer.as_ptr();
507 let mut read_frame = unsafe { CFrameItem::new_read(bit_width, buffer_ptr) };
508
509 for _ in 0..bit_width {
510 let bit = unsafe { c_readBit(&mut read_frame) };
511 mac.write_bit(bit);
512 }
513 }
514
515 if !simplicity_sys::c_jets::sanity_checks() {
517 return Err(JetFailed);
518 }
519
520 let input_width = jet.source_ty().to_bit_width();
521 let output_width = jet.target_ty().to_bit_width();
522 let (input_read_frame, _input_buffer) = unsafe { get_input_frame(self, input_width) };
525 let (mut output_write_frame, output_buffer) = unsafe { get_output_frame(output_width) };
526
527 let jet_fn = jet.c_jet_ptr();
528 let c_env = J::c_jet_env(env);
529 let success = jet_fn(&mut output_write_frame, input_read_frame, c_env);
530
531 if !success {
532 Err(JetFailed)
533 } else {
534 update_active_write_frame(self, output_width, &output_buffer);
535 Ok(())
536 }
537 }
538}
539
540#[derive(Debug)]
542pub enum ExecutionError {
543 InputWrongType(Arc<Final>),
545 ReachedFailNode(FailEntropy),
547 ReachedPrunedBranch(Cmr),
549 LimitExceeded(LimitError),
551 JetFailed(JetFailed),
553}
554
555impl fmt::Display for ExecutionError {
556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557 match self {
558 ExecutionError::InputWrongType(expected_ty) => {
559 write!(f, "Expected input of type: {expected_ty}")
560 }
561 ExecutionError::ReachedFailNode(entropy) => {
562 write!(f, "Execution reached a fail node: {}", entropy)
563 }
564 ExecutionError::ReachedPrunedBranch(hash) => {
565 write!(f, "Execution reached a pruned branch: {}", hash)
566 }
567 ExecutionError::LimitExceeded(e) => e.fmt(f),
568 ExecutionError::JetFailed(jet_failed) => jet_failed.fmt(f),
569 }
570 }
571}
572
573impl error::Error for ExecutionError {
574 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
575 match self {
576 Self::InputWrongType(..)
577 | Self::ReachedFailNode(..)
578 | Self::ReachedPrunedBranch(..) => None,
579 Self::LimitExceeded(ref e) => Some(e),
580 Self::JetFailed(ref e) => Some(e),
581 }
582 }
583}
584
585impl From<LimitError> for ExecutionError {
586 fn from(e: LimitError) -> Self {
587 ExecutionError::LimitExceeded(e)
588 }
589}
590
591impl From<JetFailed> for ExecutionError {
592 fn from(jet_failed: JetFailed) -> Self {
593 ExecutionError::JetFailed(jet_failed)
594 }
595}
596
597#[cfg(test)]
598mod tests {
599 use super::*;
600
601 #[cfg(feature = "elements")]
602 use crate::jet::{elements::ElementsEnv, Elements};
603 #[cfg(feature = "elements")]
604 use crate::{node::RedeemNode, BitIter};
605 #[cfg(feature = "elements")]
606 use hex::DisplayHex;
607
608 #[cfg(feature = "elements")]
609 fn run_program_elements(
610 prog_bytes: &[u8],
611 witness_bytes: &[u8],
612 cmr_str: &str,
613 amr_str: &str,
614 ihr_str: &str,
615 ) -> Result<Value, ExecutionError> {
616 let prog_hex = prog_bytes.as_hex();
617
618 let prog = BitIter::from(prog_bytes);
619 let witness = BitIter::from(witness_bytes);
620 let prog = match RedeemNode::<Elements>::decode(prog, witness) {
621 Ok(prog) => prog,
622 Err(e) => panic!("program {} failed: {}", prog_hex, e),
623 };
624
625 assert_eq!(
628 prog.cmr().to_string(),
629 cmr_str,
630 "CMR mismatch (got {} expected {}) for program {}",
631 prog.cmr(),
632 cmr_str,
633 prog_hex,
634 );
635 assert_eq!(
636 prog.amr().to_string(),
637 amr_str,
638 "AMR mismatch (got {} expected {}) for program {}",
639 prog.amr(),
640 amr_str,
641 prog_hex,
642 );
643 assert_eq!(
644 prog.ihr().to_string(),
645 ihr_str,
646 "IHR mismatch (got {} expected {}) for program {}",
647 prog.ihr(),
648 ihr_str,
649 prog_hex,
650 );
651
652 let env = ElementsEnv::dummy();
654 BitMachine::for_program(&prog)
655 .expect("program has reasonable bounds")
656 .exec(&prog, &env)
657 }
658
659 #[test]
660 #[cfg(feature = "elements")]
661 fn crash_regression1() {
662 let res = run_program_elements(
677 &[0xcf, 0xe1, 0x8f, 0xb4, 0x40, 0x28, 0x87, 0x04, 0x00],
678 &[],
679 "0075f5368af7b453c2f7318493df12567bc6d733cf1ebb69a08ce93e1e529956",
680 "0ac9baaee94e416c6598a271dfc18d6014f751ac300cfe69eb758c20f26c624b",
681 "61f2cf59bfec55bb6e44cbae71c3ba225f1059f9a5679c0b42a7177daff52b5a",
682 );
683 assert_eq!(res.unwrap(), Value::unit());
684 }
685
686 #[test]
687 fn crash_regression2() {
688 use crate::node::{CoreConstructible as _, JetConstructible as _};
689
690 type Node<'brand> = Arc<crate::ConstructNode<'brand, crate::jet::Core>>;
691
692 crate::types::Context::with_context(|ctx| {
693 let mut bomb = Node::jet(
694 &ctx,
695 crate::jet::Core::Ch8, );
697 for _ in 0..100 {
698 bomb = Node::pair(&bomb, &bomb).unwrap();
699 }
700 let _ = bomb.finalize_pruned(&());
701 });
702 }
703}