diff --git a/README.md b/README.md index 73b56b1..8d1993c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This repository contains the standard library for [SimplicityHL](https://github. ## Modules - asserts -- logical_operations +- binary - op_return - u8 - u16 @@ -23,9 +23,9 @@ This repository contains the standard library for [SimplicityHL](https://github. Generic assertion helpers with equality checks between uint values and validation of Option uint variants. --- -`Logical operations` +`Binary` -Basic boolean logic operations: and, or, not. +Basic binary logic operations: and, or, not, xor. --- `OP_RETURN` diff --git a/simf/logical_ops_test.simf b/simf/binary_test.simf similarity index 64% rename from simf/logical_ops_test.simf rename to simf/binary_test.simf index 45e48e4..ec4ab30 100644 --- a/simf/logical_ops_test.simf +++ b/simf/binary_test.simf @@ -1,4 +1,4 @@ -use crate::lib::logical_operations::{not, or, and}; +use crate::lib::binary::{not, or, and, xor}; fn main() { assert!(not(false)); @@ -13,4 +13,9 @@ fn main() { assert!(not(and(true, false))); assert!(not(and(false, true))); assert!(not(and(false, false))); + + assert!(xor(true, false)); + assert!(xor(false, true)); + assert!(not(xor(true, true))); + assert!(not(xor(false, false))); } diff --git a/simf/helper.simf b/simf/helper.simf index d718091..4bfc650 100644 --- a/simf/helper.simf +++ b/simf/helper.simf @@ -1,4 +1,4 @@ -use crate::lib::logical_operations::not; +use crate::lib::binary::not; pub fn if_test_this_function(index: u8, flag: u8) -> bool { jet::eq_8(index, flag) @@ -10,4 +10,4 @@ pub fn assert_bool(result: bool, expected_bool: bool) { true => assert!(result), false => assert!(not(result)), } -} \ No newline at end of file +} diff --git a/simf/lib/logical_operations.simf b/simf/lib/binary.simf similarity index 77% rename from simf/lib/logical_operations.simf rename to simf/lib/binary.simf index 63ea8e6..85f67d0 100644 --- a/simf/lib/logical_operations.simf +++ b/simf/lib/binary.simf @@ -12,3 +12,8 @@ pub fn or(a: bool, b: bool) -> bool { pub fn and(a: bool, b: bool) -> bool { ::into(jet::and_1(::into(a), ::into(b))) } + +/// Returns the result of the XOR operation on the provided values +pub fn xor(a: bool, b: bool) -> bool { + and(or(a, b), not(and(a, b))) +} diff --git a/simf/lib/secp256k1/operations.simf b/simf/lib/secp256k1/operations.simf index 510f016..0cfabbe 100644 --- a/simf/lib/secp256k1/operations.simf +++ b/simf/lib/secp256k1/operations.simf @@ -1,4 +1,4 @@ -use crate::lib::logical_operations::and; +use crate::lib::binary::and; use crate::lib::asserts::{assert_eq_1, assert_eq_256}; /// Compress an affine point to `(parity, x)`, where `parity = 1` iff `y` is odd. diff --git a/simf/lib/u128.simf b/simf/lib/u128.simf index 4c80745..5695081 100644 --- a/simf/lib/u128.simf +++ b/simf/lib/u128.simf @@ -1,4 +1,4 @@ -use crate::lib::logical_operations::{not, or, and}; +use crate::lib::binary::{not, or, and}; /// Bit logic @@ -249,6 +249,7 @@ pub fn safe_mul_128(a: u128, b: u128) -> u128 { } /// Splits the u256 integer into four u64 integers +// TODO: Move to u256 once that module is added. pub fn split_256_into_64(a: u256) -> ((u64, u64), (u64, u64)) { let (high, low): (u128, u128) = ::into(a); diff --git a/simf/u128_test.simf b/simf/u128_test.simf index 08c71f7..cbaeedf 100644 --- a/simf/u128_test.simf +++ b/simf/u128_test.simf @@ -1,6 +1,6 @@ use crate::lib::u128::{ checked_add_128, safe_add_128, checked_sub_128, safe_sub_128, checked_mul_128, safe_mul_128, checked_div_128, safe_div_128, eq_128, gt_128, ge_128 }; use crate::lib::asserts::{assert_none_128, assert_eq_128}; -use crate::lib::logical_operations::not; +use crate::lib::binary::not; use crate::helper::if_test_this_function; /// Asserts a `checked_*` result equals the expected Option. diff --git a/simf/u16_test.simf b/simf/u16_test.simf index 63d03e4..43cb52e 100644 --- a/simf/u16_test.simf +++ b/simf/u16_test.simf @@ -1,6 +1,6 @@ use crate::lib::u16::{checked_add_16, safe_add_16, checked_sub_16, safe_sub_16, checked_mul_16, safe_mul_16, checked_div_16, safe_div_16, gt_16, ge_16}; use crate::lib::asserts::{assert_none_16, assert_eq_16}; -use crate::lib::logical_operations::not; +use crate::lib::binary::not; use crate::helper::if_test_this_function; /// Asserts a `checked_*` result equals the expected Option. diff --git a/simf/u32_test.simf b/simf/u32_test.simf index 41e4f22..8636003 100644 --- a/simf/u32_test.simf +++ b/simf/u32_test.simf @@ -1,6 +1,6 @@ use crate::lib::u32::{checked_add_32, safe_add_32, checked_sub_32, safe_sub_32, checked_mul_32, safe_mul_32, checked_div_32, safe_div_32, gt_32, ge_32}; use crate::lib::asserts::{assert_none_32, assert_eq_32}; -use crate::lib::logical_operations::not; +use crate::lib::binary::not; use crate::helper::if_test_this_function; /// Asserts a `checked_*` result equals the expected Option. diff --git a/simf/u64_test.simf b/simf/u64_test.simf index 74421b4..879215f 100644 --- a/simf/u64_test.simf +++ b/simf/u64_test.simf @@ -3,7 +3,7 @@ use crate::lib::u64::{ gt_64, ge_64, u64_into_u256, }; use crate::lib::asserts::{assert_none_64, assert_eq_64}; -use crate::lib::logical_operations::not; +use crate::lib::binary::not; use crate::helper::if_test_this_function; /// Asserts a `checked_*` result equals the expected Option. diff --git a/simf/u8_test.simf b/simf/u8_test.simf index d77ee87..37e8d32 100644 --- a/simf/u8_test.simf +++ b/simf/u8_test.simf @@ -1,6 +1,6 @@ use crate::lib::u8::{checked_add_8, safe_add_8, checked_sub_8, safe_sub_8, checked_mul_8, safe_mul_8, checked_div_8, safe_div_8, gt_8, ge_8}; use crate::lib::asserts::{assert_none_8, assert_eq_8}; -use crate::lib::logical_operations::not; +use crate::lib::binary::not; use crate::helper::if_test_this_function; /// Asserts a `checked_*` result equals the expected Option. diff --git a/tests/binary_test.rs b/tests/binary_test.rs new file mode 100644 index 0000000..7bc6f50 --- /dev/null +++ b/tests/binary_test.rs @@ -0,0 +1,18 @@ +mod common; + +use common::core::{Expect, run}; + +use simplicityhl_std::artifacts::binary_test::BinaryTestProgram; +use simplicityhl_std::artifacts::binary_test::derived_binary_test::{ + BinaryTestArguments, BinaryTestWitness, +}; + +mod binary_tests { + use super::*; + + #[simplex::test] + fn binary_test(context: simplex::TestContext) -> anyhow::Result<()> { + let program = BinaryTestProgram::new(BinaryTestArguments {}); + run(&context, program, BinaryTestWitness {}, Expect::Ok) + } +} diff --git a/tests/common/uint.rs b/tests/common/uint.rs index f46230e..b52149e 100644 --- a/tests/common/uint.rs +++ b/tests/common/uint.rs @@ -67,6 +67,7 @@ fn op(o: CommonOp) -> u8 { pub fn checked_add_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::HALF_MAX); let b = rand::thread_rng().gen_range(T::ZERO..=T::HALF_MAX); + run( &context, T::program(), @@ -77,6 +78,7 @@ pub fn checked_add_fitting(context: simplex::TestContext) -> anyhow pub fn checked_add_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let b = rand::thread_rng().gen_range(T::ONE..=T::MAX); + run( &context, T::program(), @@ -88,6 +90,7 @@ pub fn checked_add_overflow(context: simplex::TestContext) -> anyho pub fn safe_add_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::HALF_MAX); let b = rand::thread_rng().gen_range(T::ZERO..=T::HALF_MAX); + run( &context, T::program(), @@ -98,6 +101,7 @@ pub fn safe_add_fitting(context: simplex::TestContext) -> anyhow::R pub fn safe_add_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let b = rand::thread_rng().gen_range(T::ONE..=T::MAX); + run( &context, T::program(), @@ -110,6 +114,7 @@ pub fn safe_add_overflow(context: simplex::TestContext) -> anyhow:: pub fn checked_sub_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); let b = rand::thread_rng().gen_range(T::ZERO..=a); + run( &context, T::program(), @@ -121,6 +126,7 @@ pub fn checked_sub_fitting(context: simplex::TestContext) -> anyhow pub fn checked_sub_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX - T::ONE); let b = rand::thread_rng().gen_range(a + T::ONE..=T::MAX); + run( &context, T::program(), @@ -132,6 +138,7 @@ pub fn checked_sub_overflow(context: simplex::TestContext) -> anyho pub fn safe_sub_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); let b = rand::thread_rng().gen_range(T::ZERO..=a); + run( &context, T::program(), @@ -143,6 +150,7 @@ pub fn safe_sub_fitting(context: simplex::TestContext) -> anyhow::R pub fn safe_sub_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX - T::ONE); let b = rand::thread_rng().gen_range(a + T::ONE..=T::MAX); + run( &context, T::program(), @@ -155,6 +163,7 @@ pub fn safe_sub_overflow(context: simplex::TestContext) -> anyhow:: pub fn checked_mul_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..T::MUL_BOUND); let b = rand::thread_rng().gen_range(T::ZERO..T::MUL_BOUND); + run( &context, T::program(), @@ -166,6 +175,7 @@ pub fn checked_mul_fitting(context: simplex::TestContext) -> anyhow pub fn checked_mul_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let two = T::ONE + T::ONE; let b = rand::thread_rng().gen_range(two..=T::MAX); + run( &context, T::program(), @@ -177,6 +187,7 @@ pub fn checked_mul_overflow(context: simplex::TestContext) -> anyho pub fn safe_mul_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..T::MUL_BOUND); let b = rand::thread_rng().gen_range(T::ZERO..T::MUL_BOUND); + run( &context, T::program(), @@ -188,6 +199,7 @@ pub fn safe_mul_fitting(context: simplex::TestContext) -> anyhow::R pub fn safe_mul_overflow(context: simplex::TestContext) -> anyhow::Result<()> { let two = T::ONE + T::ONE; let b = rand::thread_rng().gen_range(two..=T::MAX); + run( &context, T::program(), @@ -200,6 +212,7 @@ pub fn safe_mul_overflow(context: simplex::TestContext) -> anyhow:: pub fn checked_div_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); let b = rand::thread_rng().gen_range(T::ONE..=T::MAX); + run( &context, T::program(), @@ -210,6 +223,7 @@ pub fn checked_div_fitting(context: simplex::TestContext) -> anyhow pub fn checked_div_by_zero(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); + run( &context, T::program(), @@ -221,6 +235,7 @@ pub fn checked_div_by_zero(context: simplex::TestContext) -> anyhow pub fn safe_div_fitting(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); let b = rand::thread_rng().gen_range(T::ONE..=T::MAX); + run( &context, T::program(), @@ -231,6 +246,7 @@ pub fn safe_div_fitting(context: simplex::TestContext) -> anyhow::R pub fn safe_div_by_zero(context: simplex::TestContext) -> anyhow::Result<()> { let a = rand::thread_rng().gen_range(T::ZERO..=T::MAX); + run( &context, T::program(), diff --git a/tests/logical_ops_test.rs b/tests/logical_ops_test.rs deleted file mode 100644 index 5b338f6..0000000 --- a/tests/logical_ops_test.rs +++ /dev/null @@ -1,18 +0,0 @@ -mod common; - -use common::core::{Expect, run}; - -use simplicityhl_std::artifacts::logical_ops_test::LogicalOpsTestProgram; -use simplicityhl_std::artifacts::logical_ops_test::derived_logical_ops_test::{ - LogicalOpsTestArguments, LogicalOpsTestWitness, -}; - -mod logical_ops_tests { - use super::*; - - #[simplex::test] - fn logical_operations_test(context: simplex::TestContext) -> anyhow::Result<()> { - let program = LogicalOpsTestProgram::new(LogicalOpsTestArguments {}); - run(&context, program, LogicalOpsTestWitness {}, Expect::Ok) - } -}