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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Added
- Extended functions for retrieving information from `OP_RETURN`.
- Conversion and bit functions for `u2`.
- Conversion and bit functions for `u2` and `u4`.

### Changed
- Bumped Simplex to 0.2.0.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ simf/lib
│ └── convert.simf
│ └── Conversions from `u1` to other uint types and `bool`.
├── u2
├── u4
│ ├── bit.simf
│ │ └── Basic bitwise operations (`and`, `or`, `eq`).
│ └── convert.simf
│ └── Conversions between `u2` and other uint types.
│ └── Conversions between `u2`, `u4` and other uint types.
├── u8
├── u16
├── u32
Expand Down
77 changes: 77 additions & 0 deletions docs/stdlib.json
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,83 @@
"output_type": "u1",
"description": "Narrow a `u2` value to a `u1` value.\n\n## Panics\nPanics if the value does not fit in `u1`."
},
{
"simplicityhl_name": "and_4",
"section": "`u4` bit logic",
"input_type": "u4, u4",
"output_type": "u4",
"description": "Bitwise AND of two `u4` values."
},
{
"simplicityhl_name": "or_4",
"section": "`u4` bit logic",
"input_type": "u4, u4",
"output_type": "u4",
"description": "Bitwise OR of two `u4` values."
},
{
"simplicityhl_name": "eq_4",
"section": "`u4` bit logic",
"input_type": "u4, u4",
"output_type": "bool",
"description": "Check whether two `u4` values are equal."
},
{
"simplicityhl_name": "u4_to_u8",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u8",
"description": "Widen a `u4` value to a `u8` value, zero-extending the high bits."
},
{
"simplicityhl_name": "u4_to_u16",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u16",
"description": "Widen a `u4` value to a `u16` value, zero-extending the high bits."
},
{
"simplicityhl_name": "u4_to_u32",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u32",
"description": "Widen a `u4` value to a `u32` value, zero-extending the high bits."
},
{
"simplicityhl_name": "u4_to_u64",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u64",
"description": "Widen a `u4` value to a `u64` value, zero-extending the high bits."
},
{
"simplicityhl_name": "u4_to_u128",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u128",
"description": "Widen a `u4` value to a `u128` value, zero-extending the high bits."
},
{
"simplicityhl_name": "u4_to_u256",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u256",
"description": "Widen a `u4` value to a `u256` value, zero-extending the high bits."
},
{
"simplicityhl_name": "split_u4_into_u1",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "(u1, u1, u1, u1)",
"description": "Split a `u4` value into four `u1` words, most-significant first."
},
{
"simplicityhl_name": "safe_u4_to_u1",
"section": "`u4` conversions",
"input_type": "u4",
"output_type": "u1",
"description": "Narrow a `u4` value to a `u1` value.\n\n## Panics\nPanics if the value does not fit in `u1`."
},
{
"simplicityhl_name": "checked_add_8",
"section": "`u8` arithmetic",
Expand Down
27 changes: 27 additions & 0 deletions simf/lib/u4/bit.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::lib::u4::convert::u4_to_u8;

/// Bitwise AND of two 4-bit values
pub fn and_4(a: u4, b: u4) -> u4 {
let a_u8: u8 = u4_to_u8(a);
let b_u8: u8 = u4_to_u8(b);

let (_, result): (u4, u4) = <u8>::into(jet::and_8(a_u8, b_u8));
result
}

/// Bitwise OR of two 4-bit values
pub fn or_4(a: u4, b: u4) -> u4 {
let a_u8: u8 = u4_to_u8(a);
let b_u8: u8 = u4_to_u8(b);

let (_, result): (u4, u4) = <u8>::into(jet::or_8(a_u8, b_u8));
result
}

/// Checks if two 4-bit values are equal
pub fn eq_4(a: u4, b: u4) -> bool {
let a_u8: u8 = u4_to_u8(a);
let b_u8: u8 = u4_to_u8(b);

jet::eq_8(a_u8, b_u8)
}
61 changes: 61 additions & 0 deletions simf/lib/u4/convert.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/// Widening uint conversions

/// Converts u4 to u8
pub fn u4_to_u8(a: u4) -> u8 {
<(u4, u4)>::into((0, a))
}

/// Converts u4 to u16
pub fn u4_to_u16(a: u4) -> u16 {
let a_u8: u8 = u4_to_u8(a);

jet::left_pad_low_8_16(a_u8)
}

/// Converts u4 to u32
pub fn u4_to_u32(a: u4) -> u32 {
let a_u8: u8 = u4_to_u8(a);

jet::left_pad_low_8_32(a_u8)
}

/// Converts u4 to u64
pub fn u4_to_u64(a: u4) -> u64 {
let a_u8: u8 = u4_to_u8(a);

jet::left_pad_low_8_64(a_u8)
}

/// Converts u4 to u128
pub fn u4_to_u128(a: u4) -> u128 {
let a_u64: u64 = u4_to_u64(a);

<(u64, u64)>::into((0, a_u64))
}

/// Converts u4 to u256
pub fn u4_to_u256(a: u4) -> u256 {
let a_u128: u128 = u4_to_u128(a);

<(u128, u128)>::into((0, a_u128))
}

/// Splitting uint conversions

/// Splits u4 into four u1
pub fn split_u4_into_u1(a: u4) -> (u1, u1, u1, u1) {
<u4>::into(a)
}

/// Narrowing uint conversions

/// Converts u4 into u1.
/// Panics if the value does not fit in u1
pub fn safe_u4_to_u1(a: u4) -> u1 {
let u1_max: u8 = jet::left_pad_low_1_8(jet::high_1());
let a_u8: u8 = u4_to_u8(a);

assert!(jet::le_8(a_u8, u1_max));

jet::rightmost_8_1(a_u8)
}
33 changes: 33 additions & 0 deletions simf/tests/u4/bit.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::lib::u4::bit::{and_4, or_4, eq_4};

use crate::tests::support::dispatch::is_selected;
use crate::tests::support::expect::assert_bool;

fn main() {
let fn_idx: u8 = witness::FUNCTION_INDEX;

let a: u4 = witness::FIRST_ARG;
let b: u4 = witness::SECOND_ARG;
let expected: Option<u4> = witness::EXPECTED;

let expected_bool: bool = witness::EXPECTED_BOOL;

match is_selected(0, fn_idx) {
true => {
assert!(eq_4(and_4(a, b), unwrap(expected)));
},
false => (),
};
match is_selected(1, fn_idx) {
true => {
assert!(eq_4(or_4(a, b), unwrap(expected)));
},
false => (),
};
match is_selected(2, fn_idx) {
true => {
assert_bool(eq_4(a, b), expected_bool);
},
false => (),
};
}
109 changes: 109 additions & 0 deletions simf/tests/u4/convert.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::lib::u4::convert::{
u4_to_u8,
u4_to_u16,
u4_to_u32,
u4_to_u64,
u4_to_u128,
u4_to_u256,
split_u4_into_u1,
safe_u4_to_u1
};
use crate::lib::asserts::{
assert_eq_1,
assert_eq_8,
assert_eq_16,
assert_eq_32,
assert_eq_64,
assert_eq_128,
assert_eq_256
};

use crate::tests::support::dispatch::is_selected;

fn main() {
let fn_idx: u8 = witness::FUNCTION_INDEX;

let a: u4 = witness::FIRST_ARG;

let expected: u256 = witness::EXPECTED;
let (_, _, _, expected_64): (u64, u64, u64, u64) = <u256>::into(expected);

match is_selected(0, fn_idx) {
true => {
let expected: u8 = jet::rightmost_64_8(expected_64);

assert_eq_8(u4_to_u8(a), expected);
},
false => (),
};

match is_selected(1, fn_idx) {
true => {
let expected: u16 = jet::rightmost_64_16(expected_64);

assert_eq_16(u4_to_u16(a), expected);
},
false => (),
};

match is_selected(2, fn_idx) {
true => {
let expected: u32 = jet::rightmost_64_32(expected_64);

assert_eq_32(u4_to_u32(a), expected);
},
false => (),
};

match is_selected(3, fn_idx) {
true => {
assert_eq_64(u4_to_u64(a), expected_64);
},
false => (),
};

match is_selected(4, fn_idx) {
true => {
let (_, expected): (u128, u128) = <u256>::into(expected);

assert_eq_128(u4_to_u128(a), expected);
},
false => (),
};

match is_selected(5, fn_idx) {
true => {
assert_eq_256(u4_to_u256(a), expected);
},
false => (),
};

match is_selected(6, fn_idx) {
true => {
let (a3, a2, a1, a0): (u1, u1, u1, u1) = split_u4_into_u1(a);

let expected: u4 = jet::rightmost_64_4(expected_64);
let (
expected3,
expected2,
expected1,
expected0
): (u1, u1, u1, u1) = <u4>::into(expected);

assert_eq_1(a3, expected3);
assert_eq_1(a2, expected2);
assert_eq_1(a1, expected1);
assert_eq_1(a0, expected0);
},
false => (),
};

match is_selected(7, fn_idx) {
true => {
let expected: u1 = jet::rightmost_64_1(expected_64);

assert_eq_1(safe_u4_to_u1(a), expected);
},
false => (),
};
}
9 changes: 1 addition & 8 deletions simf/tests/utxo/op_return.simf
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,13 @@ use crate::lib::utxo::op_return::{
};

use crate::lib::u2::bit::eq_2;
use crate::lib::u4::bit::eq_4;
use crate::lib::asserts::assert_eq_8;
use crate::lib::u8::convert::safe_u8_to_u1;

use crate::tests::support::dispatch::is_selected;
use crate::tests::support::expect::assert_bool;

// todo: move to lib
fn eq_4(a: u4, b: u4) -> bool {
let a_u8: u8 = <(u4, u4)>::into((0, a));
let b_u8: u8 = <(u4, u4)>::into((0, b));

jet::eq_8(a_u8, b_u8)
}

fn eq_pushed_data(a: (u2, u256), b: (u2, u256)) -> bool {
let (indicator_a, hash_a): (u2, u256) = a;
let (indicator_b, hash_b): (u2, u256) = b;
Expand Down
1 change: 1 addition & 0 deletions tests/stdlib/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod u16;
mod u2;
mod u256;
mod u32;
mod u4;
mod u64;
mod u8;
mod utxo;
Loading
Loading