Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,16 @@ jobs:
run: |
cargo test --locked --manifest-path simplicity-sys/Cargo.toml
cargo test --locked --workspace --all-features

docs:
name: Docs
runs-on: ubuntu-latest
steps:
- name: Checkout Crate
uses: actions/checkout@v4
- name: Checkout Toolchain
uses: dtolnay/rust-toolchain@nightly
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

36ff961: an unpinned nightly version might lead to flaky CI, but it should be ok for checking if docs build.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have one :). I figured we could pin both instances at once. (Which we should do!)

- name: Check that documentation builds without errors
env:
RUSTDOCFLAGS: "--cfg docsrs -D warnings -D rustdoc::broken-intra-doc-links"
run: cargo doc -j1 --all-features
50 changes: 38 additions & 12 deletions src/bit_machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::types::Final;
use crate::{analysis, Ihr};
use crate::{Cmr, FailEntropy, Value};
use frame::Frame;
use simplicity_sys::ffi::UWORD;

pub use self::limits::LimitError;

Expand Down Expand Up @@ -242,7 +243,12 @@ impl BitMachine {
Ok(tracker)
}

fn exec_with_tracker<J: Jet, T: CaseTracker>(
/// Execute the given `program` on the Bit Machine, using the given environment and tracker.
///
/// ## Precondition
///
/// The Bit Machine is constructed via [`Self::for_program()`] to ensure enough space.
pub fn exec_with_tracker<J: Jet, T: ExecTracker<J>>(
&mut self,
program: &RedeemNode<J>,
env: &J::Environment,
Expand Down Expand Up @@ -371,7 +377,7 @@ impl BitMachine {
}
}
node::Inner::Witness(value) => self.write_value(value),
node::Inner::Jet(jet) => self.exec_jet(*jet, env)?,
node::Inner::Jet(jet) => self.exec_jet(*jet, env, tracker)?,
node::Inner::Word(value) => self.write_value(value.as_value()),
node::Inner::Fail(entropy) => {
return Err(ExecutionError::ReachedFailNode(*entropy))
Expand Down Expand Up @@ -408,7 +414,12 @@ impl BitMachine {
}
}

fn exec_jet<J: Jet>(&mut self, jet: J, env: &J::Environment) -> Result<(), JetFailed> {
fn exec_jet<J: Jet, T: ExecTracker<J>>(
&mut self,
jet: J,
env: &J::Environment,
tracker: &mut T,
) -> Result<(), JetFailed> {
use crate::ffi::c_jets::frame_ffi::{c_readBit, c_writeBit, CFrameItem};
use crate::ffi::c_jets::uword_width;
use crate::ffi::ffi::UWORD;
Expand Down Expand Up @@ -494,13 +505,15 @@ impl BitMachine {
let output_width = jet.target_ty().to_bit_width();
// Input buffer is implicitly referenced by input read frame!
// Same goes for output buffer
let (input_read_frame, _input_buffer) = unsafe { get_input_frame(self, input_width) };
let (input_read_frame, input_buffer) = unsafe { get_input_frame(self, input_width) };
let (mut output_write_frame, output_buffer) = unsafe { get_output_frame(output_width) };

let jet_fn = jet.c_jet_ptr();
let c_env = J::c_jet_env(env);
let success = jet_fn(&mut output_write_frame, input_read_frame, c_env);

tracker.track_jet_call(&jet, &input_buffer, &output_buffer, success);

if !success {
Err(JetFailed)
} else {
Expand All @@ -510,25 +523,33 @@ impl BitMachine {
}
}

/// A type that keeps track of which case branches were executed
/// during the execution of the Bit Machine.
/// A type that keeps track of Bit Machine execution.
///
/// The trait is implemented for [`SetTracker`], which does the actual tracking,
/// The trait is implemented for [`SetTracker`], that tracks which case branches were executed,
/// and it is implemented for [`NoTracker`], which is a dummy tracker that is
Comment thread
uncomputable marked this conversation as resolved.
/// optimized out by the compiler.
///
/// The trait enables us to turn tracking on or off depending on a generic parameter.
trait CaseTracker {
pub trait ExecTracker<J: Jet> {
/// Track the execution of the left branch of the case node with the given `ihr`.
fn track_left(&mut self, ihr: Ihr);

/// Track the execution of the right branch of the case node with the given `ihr`.
fn track_right(&mut self, ihr: Ihr);

/// Track the execution of a `jet` call with the given `input_buffer`, `output_buffer`, and call result `success`.
fn track_jet_call(
&mut self,
jet: &J,
input_buffer: &[UWORD],
output_buffer: &[UWORD],
success: bool,
);
}

/// Tracker of executed left and right branches for each case node.
#[derive(Clone, Debug, Default)]
pub(crate) struct SetTracker {
pub struct SetTracker {
left: HashSet<Ihr>,
right: HashSet<Ihr>,
}
Expand All @@ -545,23 +566,28 @@ impl SetTracker {
}
}

/// Tracker that does not do anything (noop).
#[derive(Copy, Clone, Debug)]
struct NoTracker;
pub struct NoTracker;

impl CaseTracker for SetTracker {
impl<J: Jet> ExecTracker<J> for SetTracker {
fn track_left(&mut self, ihr: Ihr) {
self.left.insert(ihr);
}

fn track_right(&mut self, ihr: Ihr) {
self.right.insert(ihr);
}

fn track_jet_call(&mut self, _: &J, _: &[UWORD], _: &[UWORD], _: bool) {}
}

impl CaseTracker for NoTracker {
impl<J: Jet> ExecTracker<J> for NoTracker {
fn track_left(&mut self, _: Ihr) {}

fn track_right(&mut self, _: Ihr) {}

fn track_jet_call(&mut self, _: &J, _: &[UWORD], _: &[UWORD], _: bool) {}
}

/// Errors related to simplicity Execution
Expand Down