Skip to content

Commit fc27a3f

Browse files
committed
Use simplicity-sys for running test programs
1 parent a522ee4 commit fc27a3f

File tree

10 files changed

+69
-57
lines changed

10 files changed

+69
-57
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ jobs:
2121

2222
test-stable:
2323
name: Test - stable toolchain
24-
runs-on: ubuntu-latest
24+
runs-on: ${{ matrix.os }}
25+
strategy:
26+
matrix:
27+
os: [ubuntu-latest, macos-latest]
2528

2629
steps:
2730
- name: Checkout

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ homepage = "https://github.com/BlockstreamResearch/simfony/"
77
repository = "https://github.com/BlockstreamResearch/simfony/"
88
description = "Rust-like language that compiles to Simplicity bytecode."
99
edition = "2021"
10-
rust-version = "1.63.0"
10+
rust-version = "1.78.0"
1111

1212
[lib]
1313
name = "simfony"
@@ -22,12 +22,11 @@ serde = ["dep:serde", "dep:serde_json"]
2222

2323
[dependencies]
2424
base64 = "0.21.2"
25-
hex-conservative = "0.1.1"
2625
pest = "2.1.3"
2726
pest_derive = "2.7.1"
2827
serde = { version = "1.0.188", features = ["derive"], optional = true }
2928
serde_json = { version = "1.0.105", optional = true }
30-
simplicity-lang = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "ca0c0ebee295937ab021ad018acc44a5aaa12649" }
29+
simplicity-lang = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "b0f851cb33677d8be3b5a6dce66f1665d35760a8", features = ["test-utils"]}
3130
miniscript = "12.2.0"
3231
either = "1.12.0"
3332
itertools = "0.13.0"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Take a look at the [example programs](https://github.com/BlockstreamResearch/sim
2020

2121
## MSRV
2222

23-
This crate should compile with any feature combination on **Rust 1.63.0** or higher.
23+
This crate should compile with any feature combination on **Rust 1.78.0** or higher.
2424

2525
## Simplicity's need for a high-level language
2626

clippy.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
msrv = "1.63.0"
1+
msrv = "1.78.0"

codegen/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
name = "codegen"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.63.0"
65
description = "Generator of Rust code as interface between Simfony and Rust."
76
publish = false
87

flake.nix

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@
1414
, rust-overlay
1515
, ...
1616
}:
17-
flake-utils.lib.eachSystem [
18-
"x86_64-linux"
19-
"aarch64-linux"
20-
"x86_64-darwin"
21-
] (system:
17+
flake-utils.lib.eachDefaultSystem
18+
(system:
2219
let
2320
overlays = [
2421
(import rust-overlay)
@@ -35,23 +32,24 @@
3532
CC_wasm32_unknown_unknown = "${pkgs.llvmPackages_16.clang-unwrapped}/bin/clang-16";
3633
AR_wasm32_unknown_unknown = "${pkgs.llvmPackages_16.libllvm}/bin/llvm-ar";
3734
CFLAGS_wasm32_unknown_unknown = "-I ${pkgs.llvmPackages_16.libclang.lib}/lib/clang/16/include/";
35+
gdbSupported = !(pkgs.stdenv.isDarwin && pkgs.stdenv.isAarch64);
3836
default_shell = with_elements: pkgs.mkShell {
3937
buildInputs = [
4038
defaultRust
4139
pkgs.just
42-
pkgs.gdb
4340
pkgs.cargo-hack
4441
pkgs.mdbook
4542
] ++ (
4643
if with_elements then [ elementsd-simplicity ] else []
44+
) ++ (
45+
if gdbSupported then [ pkgs.gdb ] else []
4746
);
4847
inherit CC_wasm32_unknown_unknown;
4948
inherit AR_wasm32_unknown_unknown;
5049
inherit CFLAGS_wasm32_unknown_unknown;
5150
# Constants for IDE
5251
RUST_TOOLCHAIN = "${defaultRust}/bin";
5352
RUST_STDLIB = "${defaultRust}/lib/rustlib/src/rust";
54-
DEBUGGER = "${pkgs.gdb}";
5553
};
5654
in
5755
{
@@ -68,7 +66,7 @@
6866
};
6967
msrv = pkgs.mkShell {
7068
buildInputs = [
71-
(mkRust "stable" "1.63.0" "minimal" [] [])
69+
(mkRust "stable" "1.78.0" "minimal" [] [])
7270
pkgs.just
7371
];
7472
};

src/lib.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,8 @@ pub trait ArbitraryOfType: Sized {
249249
mod tests {
250250
use base64::display::Base64Display;
251251
use base64::engine::general_purpose::STANDARD;
252-
#[cfg(feature = "serde")]
253-
use elements::LockTime;
254-
use simplicity::BitMachine;
252+
use simplicity::ffi::tests::ffi::SimplicityErr;
253+
use simplicity::ffi::tests::{run_program, TestUpTo};
255254
use std::borrow::Cow;
256255
use std::path::Path;
257256

@@ -391,10 +390,10 @@ mod tests {
391390
self
392391
}
393392

394-
fn run(self) -> Result<(), simplicity::bit_machine::ExecutionError> {
395-
let mut mac = BitMachine::for_program(self.program.redeem());
396-
let env = dummy_env::dummy_with(self.lock_time, self.sequence, self.include_fee_output);
397-
mac.exec(self.program.redeem(), &env).map(|_| ())
393+
fn run(self) -> Result<(), SimplicityErr> {
394+
let (program_bytes, witness_bytes) = self.program.redeem().encode_to_vec();
395+
let _ = run_program(&program_bytes, &witness_bytes, TestUpTo::Everything)?;
396+
Ok(())
398397
}
399398

400399
pub fn assert_run_success(self) {
@@ -425,7 +424,7 @@ mod tests {
425424
let mut t = TestCase::program_file("./examples/non_interactive_fee_bump.simf")
426425
.with_witness_file("./examples/non_interactive_fee_bump.wit");
427426
t.sequence = elements::Sequence::ENABLE_LOCKTIME_NO_RBF;
428-
t.lock_time = LockTime::from_time(1734967235 + 600).unwrap();
427+
t.lock_time = elements::LockTime::from_time(1734967235 + 600).unwrap();
429428
t.include_fee_output = true;
430429
t.assert_run_success();
431430
}
@@ -613,8 +612,22 @@ fn main() {
613612
fn main() {
614613
let x: MyAlias = 32;
615614
assert!(jet::eq_32(x, 32));
616-
}
617-
"#;
615+
}"#;
616+
TestCase::program_text(Cow::Borrowed(prog_text))
617+
.with_witness_values(WitnessValues::default())
618+
.assert_run_success();
619+
}
620+
621+
#[test]
622+
fn type_error_regression() {
623+
let prog_text = r#"fn main() {
624+
let (a, b): (u32, u32) = (0, 1);
625+
assert!(jet::eq_32(a, 0));
626+
627+
let (c, d): (u32, u32) = (2, 3);
628+
assert!(jet::eq_32(c, 2));
629+
assert!(jet::eq_32(d, 3));
630+
}"#;
618631
TestCase::program_text(Cow::Borrowed(prog_text))
619632
.with_witness_values(WitnessValues::default())
620633
.assert_run_success();

src/named.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use std::sync::Arc;
33
use simplicity::dag::{InternalSharing, PostOrderIterItem};
44
use simplicity::jet::{Elements, Jet};
55
use simplicity::node::{
6-
self, CommitData, Constructible, Converter, CoreConstructible, Inner, JetConstructible,
7-
NoDisconnect, NoWitness, Node, WitnessConstructible, WitnessData,
6+
self, CommitData, ConstructData as WitnessData, Constructible, Converter, CoreConstructible,
7+
Inner, JetConstructible, NoDisconnect, NoWitness, Node, WitnessConstructible,
88
};
99
use simplicity::types::arrow::Arrow;
1010
use simplicity::{types, CommitNode, FailEntropy};
11-
use simplicity::{Cmr, WitnessNode};
11+
use simplicity::{Cmr, ConstructNode as WitnessNode};
1212

1313
use crate::str::WitnessName;
1414
use crate::value::StructuralValue;
@@ -105,7 +105,7 @@ pub fn to_witness_node(node: &ConstructNode, values: WitnessValues) -> Arc<Witne
105105
inference_context: types::Context,
106106
}
107107

108-
impl<J: Jet> Converter<Construct<J>, node::Witness<J>> for Populator {
108+
impl<J: Jet> Converter<Construct<J>, node::Construct<J>> for Populator {
109109
type Error = ();
110110

111111
fn convert_witness(

src/value.rs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::fmt;
22
use std::sync::Arc;
33

44
use either::Either;
5-
use hex_conservative::DisplayHex;
5+
use miniscript::bitcoin::hex::DisplayHex;
66
use miniscript::iter::{Tree, TreeLike};
77
use simplicity::types::Final as SimType;
8-
use simplicity::{BitCollector, Value as SimValue};
8+
use simplicity::{BitCollector, Value as SimValue, ValueRef};
99

1010
use crate::array::{BTreeSlice, Combiner, Partition, Unfolder};
1111
use crate::error::{Error, RichError, WithSpan};
@@ -623,7 +623,7 @@ impl Value {
623623

624624
/// Create a value from the given `hexadecimal` string and type.
625625
pub fn parse_hexadecimal(hexadecimal: &Hexadecimal, ty: &ResolvedType) -> Result<Self, Error> {
626-
use hex_conservative::FromHex;
626+
use miniscript::bitcoin::hex::FromHex;
627627

628628
let expected_byte_len = match ty.as_inner() {
629629
TypeInner::UInt(int) => int.byte_width(),
@@ -730,11 +730,11 @@ impl Value {
730730
pub fn reconstruct(value: &StructuralValue, ty: &ResolvedType) -> Option<Self> {
731731
let mut output = vec![];
732732
for data in value.destruct(ty).post_order_iter() {
733+
let size = data.node.n_children();
733734
let (value, ty) = match data.node {
734735
Destructor::Ok { value, ty } => (value, ty),
735736
Destructor::WrongType => return None,
736737
};
737-
let size = data.node.n_children();
738738
match ty.as_inner() {
739739
TypeInner::Boolean => {
740740
let bit = destruct::as_bit(value)?;
@@ -877,10 +877,10 @@ impl TreeLike for StructuralValue {
877877
fn as_node(&self) -> Tree<Self> {
878878
use simplicity::dag::{Dag, DagLike};
879879

880-
match (&self.0).as_dag_node() {
880+
match self.0.as_ref().as_dag_node() {
881881
Dag::Nullary => Tree::Nullary,
882-
Dag::Unary(l) => Tree::Unary(Self(l.shallow_clone())),
883-
Dag::Binary(l, r) => Tree::Binary(Self(l.shallow_clone()), Self(r.shallow_clone())),
882+
Dag::Unary(l) => Tree::Unary(Self(l.to_value())),
883+
Dag::Binary(l, r) => Tree::Binary(Self(l.to_value()), Self(r.to_value())),
884884
}
885885
}
886886
}
@@ -1059,7 +1059,7 @@ impl StructuralValue {
10591059

10601060
fn destruct<'a>(&'a self, ty: &'a ResolvedType) -> Destructor<'a> {
10611061
Destructor::Ok {
1062-
value: self.as_ref(),
1062+
value: self.0.as_ref(),
10631063
ty,
10641064
}
10651065
}
@@ -1091,30 +1091,30 @@ impl StructuralValue {
10911091
/// The leaf values (Boolean, unsigned integer, empty tuple, empty array) are not checked.
10921092
/// Extraction of actual Simfony values (Boolean, unsigned integer, ...)
10931093
/// from the leaf Simplicity values may fail, in which case the entire tree is, again, ill-typed.
1094-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1094+
#[derive(Clone, Debug)]
10951095
enum Destructor<'a> {
10961096
Ok {
1097-
value: &'a SimValue,
1097+
value: ValueRef<'a>,
10981098
ty: &'a ResolvedType,
10991099
},
11001100
WrongType,
11011101
}
11021102

11031103
impl<'a> Destructor<'a> {
11041104
/// Create a destructor for the given Simplicity `value` and the given Simfony type.
1105-
pub const fn new(value: &'a SimValue, ty: &'a ResolvedType) -> Self {
1105+
pub const fn new(value: ValueRef<'a>, ty: &'a ResolvedType) -> Self {
11061106
Self::Ok { value, ty }
11071107
}
11081108

1109-
const fn new_pair((value, ty): (&'a SimValue, &'a ResolvedType)) -> Self {
1109+
const fn new_pair((value, ty): (ValueRef<'a>, &'a ResolvedType)) -> Self {
11101110
Self::Ok { value, ty }
11111111
}
11121112
}
11131113

11141114
impl TreeLike for Destructor<'_> {
11151115
fn as_node(&self) -> Tree<Self> {
11161116
let (value, ty) = match self {
1117-
Self::Ok { value, ty } => (value, ty),
1117+
Self::Ok { value, ty } => (value.clone(), ty),
11181118
Self::WrongType => return Tree::Nullary,
11191119
};
11201120
match ty.as_inner() {
@@ -1166,8 +1166,9 @@ impl TreeLike for Destructor<'_> {
11661166
/// Functions for destructing Simplicity values alongside Simfony types.
11671167
mod destruct {
11681168
use super::*;
1169+
use simplicity::ValueRef;
11691170

1170-
pub fn as_bit(value: &SimValue) -> Option<bool> {
1171+
pub fn as_bit(value: ValueRef) -> Option<bool> {
11711172
match value.as_left() {
11721173
Some(unit) if unit.is_unit() => Some(false),
11731174
_ => match value.as_right() {
@@ -1177,10 +1178,10 @@ mod destruct {
11771178
}
11781179
}
11791180

1180-
pub fn as_integer(value: &SimValue, ty: UIntType) -> Option<UIntValue> {
1181+
pub fn as_integer(value: ValueRef, ty: UIntType) -> Option<UIntValue> {
11811182
let bit_len = ty.bit_width().get();
11821183
let unfolder = Unfolder::new(value, bit_len);
1183-
let bit_values = unfolder.unfold(SimValue::as_product)?;
1184+
let bit_values = unfolder.unfold(|v| v.as_product())?;
11841185
let (bytes, written_bits) = bit_values.into_iter().filter_map(as_bit).collect_bits();
11851186
if bit_len != written_bits {
11861187
return None;
@@ -1196,31 +1197,31 @@ mod destruct {
11961197
}
11971198
}
11981199

1199-
pub fn as_tuple(value: &SimValue, size: usize) -> Option<Vec<&SimValue>> {
1200-
Unfolder::new(value, size).unfold(SimValue::as_product)
1200+
pub fn as_tuple(value: ValueRef, size: usize) -> Option<Vec<ValueRef>> {
1201+
Unfolder::new(value, size).unfold(|v| v.as_product())
12011202
}
12021203

1203-
pub fn as_array(value: &SimValue, size: usize) -> Option<Vec<&SimValue>> {
1204-
Unfolder::new(value, size).unfold(SimValue::as_product)
1204+
pub fn as_array(value: ValueRef, size: usize) -> Option<Vec<ValueRef>> {
1205+
Unfolder::new(value, size).unfold(|v| v.as_product())
12051206
}
12061207

1207-
pub fn as_list<'a>(value: &'a SimValue, bound: NonZeroPow2Usize) -> Option<Vec<&'a SimValue>> {
1208-
let as_block = |value: &'a SimValue, size: usize| match as_option(value) {
1208+
pub fn as_list<'a>(value: ValueRef<'a>, bound: NonZeroPow2Usize) -> Option<Vec<ValueRef<'a>>> {
1209+
let as_block = |value: ValueRef<'a>, size: usize| match as_option(value) {
12091210
Some(Some(folded)) => as_array(folded, size),
12101211
Some(None) => Some(vec![]),
12111212
None => None,
12121213
};
1213-
Combiner::new(value, bound).unfold(as_block, SimValue::as_product)
1214+
Combiner::new(value, bound).unfold(as_block, |v| v.as_product())
12141215
}
12151216

1216-
pub fn as_either(value: &SimValue) -> Option<Either<&SimValue, &SimValue>> {
1217+
pub fn as_either(value: ValueRef) -> Option<Either<ValueRef, ValueRef>> {
12171218
match value.as_left() {
12181219
Some(inner) => Some(Either::Left(inner)),
12191220
None => value.as_right().map(Either::Right),
12201221
}
12211222
}
12221223

1223-
pub fn as_option(value: &SimValue) -> Option<Option<&SimValue>> {
1224+
pub fn as_option(value: ValueRef) -> Option<Option<ValueRef>> {
12241225
match value.as_left() {
12251226
Some(inner) if inner.is_unit() => Some(None),
12261227
_ => value.as_right().map(Some),

0 commit comments

Comments
 (0)