From cf13455c0e407febbc16c55ed429613c2ef76617 Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Thu, 14 May 2026 18:41:04 +0300 Subject: [PATCH 01/13] Initial version (#8) * added simplex template * added assert functions with test * documented functions in asserts file * added todo comment * updated simplex version to 0.0.5 --- .github/ISSUE_TEMPLATE/bug-report.yml | 30 + .github/ISSUE_TEMPLATE/feature-request.yml | 13 + .github/ISSUE_TEMPLATE/other-issue.md | 4 + .github/actions/setup-smplx/action.yml | 22 + .github/scripts/setup-smplx | 68 + .github/workflows/tests.yml | 61 + .gitignore | 12 + Cargo.lock | 1897 ++++++++++++++++++++ Cargo.toml | 10 + LICENSE | 21 + Simplex.toml | 27 + simf/asserts.simf | 57 + simf/mock/asserts_mock.simf | 66 + src/lib.rs | 1 + tests/asserts_test.rs | 59 + 15 files changed, 2348 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml create mode 100644 .github/ISSUE_TEMPLATE/other-issue.md create mode 100644 .github/actions/setup-smplx/action.yml create mode 100644 .github/scripts/setup-smplx create mode 100644 .github/workflows/tests.yml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 Simplex.toml create mode 100644 simf/asserts.simf create mode 100644 simf/mock/asserts_mock.simf create mode 100644 src/lib.rs create mode 100644 tests/asserts_test.rs diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..8878aac --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,30 @@ +name: Bug Report +description: File a bug report +labels: ['bug'] +assignees: + - +body: + - type: markdown + attributes: + value: Thanks for taking the time to fill out this bug report! + - type: input + id: version + attributes: + label: "Project version" + placeholder: "0.1.2" + validations: + required: true + - type: textarea + id: what-happened + attributes: + label: What happened? + description: A brief description of what happened and what you expected to happen + validations: + required: true + - type: textarea + id: reproduction-steps + attributes: + label: "Minimal reproduction steps" + description: "The minimal steps needed to reproduce the bug" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..290a178 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,13 @@ +name: Feature request +description: Suggest a new feature +labels: ['feature'] +assignees: + - +body: + - type: textarea + id: feature-description + attributes: + label: "Describe the feature" + description: "A description of what you would like to see in the project" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/other-issue.md b/.github/ISSUE_TEMPLATE/other-issue.md new file mode 100644 index 0000000..7115534 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other-issue.md @@ -0,0 +1,4 @@ +--- +name: Other issue +about: Other kind of issue +--- diff --git a/.github/actions/setup-smplx/action.yml b/.github/actions/setup-smplx/action.yml new file mode 100644 index 0000000..e118fdf --- /dev/null +++ b/.github/actions/setup-smplx/action.yml @@ -0,0 +1,22 @@ +name: setup-smplx + +inputs: + commit-sha: + description: "Commit in repository to use" + required: false + default: "master" + owner-repo: + description: "Owner repo on Github to use" + required: false + default: "BlockstreamResearch/smplx" + +runs: + using: composite + steps: + - name: Install smplx-cli via simplexup + shell: bash + run: | + set -euo pipefail + REVISION="${{ inputs.commit-sha}}" + OWNER_REPO="${{ inputs.owner-repo }}" + bash "$GITHUB_WORKSPACE/.github/scripts/setup-smplx" "${REVISION}" "${OWNER_REPO}" diff --git a/.github/scripts/setup-smplx b/.github/scripts/setup-smplx new file mode 100644 index 0000000..0cfc330 --- /dev/null +++ b/.github/scripts/setup-smplx @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -euo pipefail + +say() { + printf "setup-smplx: %s\n" "$1" +} + +err() { + say "$1" >&2 + exit 1 +} + +main() { + # Parse and validate arguments + COMMIT_SHA="${1:-}" + OWNER_REPO="${2:-}" + FETCH_REF="${COMMIT_SHA:-master}" + FILE_PATH="simplexup/install" + + if [ "$#" -lt 2 ]; then + err "Usage: setup-smplx " + fi + + if [ -z "$OWNER_REPO" ]; then + err "no OWNER_REPO variable set" + fi + + # Download and execute the initial install script + RAW_URL="https://raw.githubusercontent.com/${OWNER_REPO}/${FETCH_REF}/${FILE_PATH}" + say "Fetching ${FILE_PATH} from ${RAW_URL}" + + curl -fsSL --retry 5 --retry-all-errors --retry-delay 2 "${RAW_URL}" | bash + + # Download the simplexup executable + FILE_PATH="simplexup/simplexup" + RAW_URL="https://raw.githubusercontent.com/${OWNER_REPO}/${FETCH_REF}/${FILE_PATH}" + + BASE_DIR="${XDG_CONFIG_HOME:-$HOME}" + SIMPLEX_DIR="${SIMPLEX_DIR:-$BASE_DIR/.simplex}" + SIMPLEX_BIN_DIR="$SIMPLEX_DIR/bin" + BIN_PATH="$SIMPLEX_BIN_DIR/simplexup" + + # Ensure bin directory exists and download simplexup into it + mkdir -p "$SIMPLEX_BIN_DIR" + say "Fetching ${FILE_PATH} from ${RAW_URL}" + + curl -fsSL --retry 5 --retry-all-errors --retry-delay 2 "${RAW_URL}" -o "$BIN_PATH" + chmod +x "$BIN_PATH" + + # Execute simplexup, using a specific commit if provided (and not master's default release) + if [ "$FETCH_REF" != "master" ]; then + say "Using simplexup and simplex from commit: ${FETCH_REF}" + "$BIN_PATH" --commit "${FETCH_REF}" + else + say "Using simplexup from master branch and installing latest simplex" + "$BIN_PATH" + fi + + # Add the Simplex binary directory to GitHub Actions PATH + echo "$SIMPLEX_BIN_DIR" >> "$GITHUB_PATH" + + # Verify installation + say "Verifying simplex installation..." + "${SIMPLEX_BIN_DIR}/simplex" --version +} + +main "$@" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..03a6a52 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,61 @@ +name: Smplx-tests + +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + branches: + - master + - dev + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: full + +jobs: + simplex-tests: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + toolchain: [ "1.91.0" ] + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: true + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.toolchain }} + + - name: Use Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Install simplex-cli + uses: ./.github/actions/setup-smplx + + - name: Generate contract artifacts + shell: bash + run: | + simplex build + + - name: Build + run: | + cargo build --workspace --all-features --verbose + + - name: Test + run: | + simplex test --nocapture diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddafd0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Build output +target/ + +# Simplex output +src/artifacts + +# IDE/editors (optional but common minimal) +**/.DS_Store +.idea/ +.vscode/ +.cache +.env diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..367e18e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1897 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ar_archive_writer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +dependencies = [ + "object", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bech32" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" + +[[package]] +name = "bip39" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf93e61f2dbc3e3c41234ca26a65e2c0b0975c52e0f069ab9893ebbede584d3" +dependencies = [ + "base58ck", + "base64 0.21.7", + "bech32", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" + +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + +[[package]] +name = "bitcoin-units" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118" +dependencies = [ + "bitcoin-internals", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +dependencies = [ + "bitcoin-io", + "hex-conservative", + "serde", +] + +[[package]] +name = "bitcoincore-rpc" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedd23ae0fd321affb4bbbc36126c6f49a32818dc6b979395d24da8c9d4e80ee" +dependencies = [ + "bitcoincore-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoincore-rpc-json" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8909583c5fab98508e80ef73e5592a651c954993dc6b7739963257d19f0e71a" +dependencies = [ + "bitcoin", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoind" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce6620b7c942dbe28cc49c21d95e792feb9ffd95a093205e7875ccfa69c2925" +dependencies = [ + "anyhow", + "bitcoincore-rpc", + "log", + "tempfile", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chumsky" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acc17a6284abccac6e50db35c1cee87f605474a72939b959a3a67d9371800efd" +dependencies = [ + "hashbrown 0.15.5", + "regex-automata 0.3.9", + "serde", + "stacker", + "unicode-ident", + "unicode-segmentation", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "electrsd" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91435161fb2ad5098e7ac7a4b793bf9c34723b0208a3fcf6f33707489e771396" +dependencies = [ + "bitcoind", + "electrum-client", + "log", + "nix", + "which", +] + +[[package]] +name = "electrum-client" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0bd443023f9f5c4b7153053721939accc7113cbdf810a024434eed454b3db1" +dependencies = [ + "bitcoin", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "elements" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b2569d3495bfdfce36c504fd4d78752ff4a7699f8a33e6f3ee523bddf9f6ad" +dependencies = [ + "bech32", + "bitcoin", + "secp256k1-zkp", + "serde", + "serde_json", +] + +[[package]] +name = "elements-miniscript" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571fa105690f83c7833df2109eb2e14ca0e62d633d2624ffcb166ff18a3da870" +dependencies = [ + "bitcoin", + "elements", + "miniscript", + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "ghost-cell" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8449d342b1c67f49169e92e71deb7b9b27f30062301a16dbc27a4cc8d2351b7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.14", + "regex-syntax 0.8.10", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.11.1", + "ignore", + "walkdir", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.14", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3662a38d341d77efecb73caf01420cfa5aa63c0253fd7bc05289ef9f6616e1bf" +dependencies = [ + "base64 0.13.1", + "minreq", + "serde", + "serde_json", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniscript" +version = "12.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c14116d8342edd3626b0f8e84df16f4e6a76dc04799ba747493403236a1b8ac5" +dependencies = [ + "bech32", + "bitcoin", +] + +[[package]] +name = "minreq" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" +dependencies = [ + "rustls", + "rustls-webpki", + "serde", + "serde_json", + "webpki-roots", +] + +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" +dependencies = [ + "ar_archive_writer", + "cc", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.14", + "regex-syntax 0.8.10", +] + +[[package]] +name = "regex-automata" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.10", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "santiago" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de36022292bc2086eb8f55bffa460fef3475e4459b478820711f4c421feb87ec" +dependencies = [ + "regex", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes", + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-zkp" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a44aed3002b5ae975f8624c5df3a949cfbf00479e18778b6058fcd213b76e3" +dependencies = [ + "bitcoin-private", + "rand", + "secp256k1", + "secp256k1-zkp-sys", + "serde", +] + +[[package]] +name = "secp256k1-zkp-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57f08b2d0b143a22e07f798ae4f0ab20d5590d7c68e0d090f2088a48a21d1654" +dependencies = [ + "cc", + "secp256k1-sys", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simplicity-lang" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e57bd4d84853974a212eab24ed89da54f49fbccf5e33e93bcd29f0a6591cd5" +dependencies = [ + "bitcoin", + "bitcoin_hashes", + "byteorder", + "elements", + "getrandom 0.2.17", + "ghost-cell", + "hex-conservative", + "miniscript", + "santiago", + "simplicity-sys", +] + +[[package]] +name = "simplicity-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3401ee7331f183a5458c0f5a4b3d5d00bde0fd12e2e03728c537df34efae289" +dependencies = [ + "bitcoin_hashes", + "cc", +] + +[[package]] +name = "simplicityhl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25de8990174fe3e1a843df138cacc4265d05839ebd2550c18b9196f567d55e81" +dependencies = [ + "base64 0.21.7", + "chumsky", + "clap", + "either", + "getrandom 0.2.17", + "itertools", + "miniscript", + "serde", + "serde_json", + "simplicity-lang", +] + +[[package]] +name = "simplicityhl_std" +version = "0.1.0" +dependencies = [ + "anyhow", + "smplx-std", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smplx-build" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3170d79eafea8c119d0b491014aaf2054679ba8c285c453c2acb879b52896b5e" +dependencies = [ + "glob", + "globwalk", + "pathdiff", + "prettyplease", + "proc-macro2", + "quote", + "serde", + "simplicityhl", + "syn", + "thiserror", + "toml", +] + +[[package]] +name = "smplx-macros" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e591d0bb8c971f38ea525b5e1bc18a39b369bc1fdecc07632120142afb7e34" +dependencies = [ + "smplx-build", + "smplx-test", + "syn", +] + +[[package]] +name = "smplx-regtest" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b42c1ad54f123195eb90543e88a2e3b1519a11479862ac29a5cd7a0e24f13d7" +dependencies = [ + "electrsd", + "hex", + "hmac", + "serde", + "sha2", + "smplx-sdk", + "thiserror", + "toml", +] + +[[package]] +name = "smplx-sdk" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe05e7d0f9cef029968453f087f323df01f92e13fc240796a732cffac734074a" +dependencies = [ + "bip39", + "bitcoin_hashes", + "dyn-clone", + "electrsd", + "elements-miniscript", + "hex", + "minreq", + "serde", + "serde_json", + "sha2", + "simplicityhl", + "thiserror", +] + +[[package]] +name = "smplx-std" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8465bd3dae0d1bf37c88f2ba4144e5b5157d390a3c5e56016ff04b64ee9fc199" +dependencies = [ + "either", + "serde", + "simplicityhl", + "smplx-macros", + "smplx-sdk", + "smplx-test", +] + +[[package]] +name = "smplx-test" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1025e34b6101ab8e92b6baa4807227894ca324e0405d22a703c2ddd6c5af979" +dependencies = [ + "electrsd", + "proc-macro2", + "quote", + "serde", + "simplicityhl", + "smplx-regtest", + "smplx-sdk", + "syn", + "thiserror", + "toml", +] + +[[package]] +name = "stacker" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.61.2", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.2", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..030390b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "simplicityhl_std" +edition = "2024" +rust-version = "1.91.0" +version = "0.1.0" + +[dependencies] +smplx-std = { version = ">=0.0.5, <0.1.0" } + +anyhow = { version = "1.0.101" } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..99784d9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Blockstream + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Simplex.toml b/Simplex.toml new file mode 100644 index 0000000..1c78892 --- /dev/null +++ b/Simplex.toml @@ -0,0 +1,27 @@ +# Default Simplex Config + +# [build] +# src_dir = "./simf" +# simf_files = ["*.simf"] +# out_dir = "./src/artifacts" + +# [regtest] +# mnemonic = "exist carry drive collect lend cereal occur much tiger just involve mean" +# bitcoins = 10_000_000 +# rpc_port = 18443 +# esplora_port = 3000 +# rpc_user = "user" +# rpc_password = "password" + +# [test] +# mnemonic = "exist carry drive collect lend cereal occur much tiger just involve mean" +# bitcoins = 10_000_000 + +# [test.esplora] +# url = "" +# network = "" + +# [test.rpc] +# url = "" +# username = "" +# password = "" diff --git a/simf/asserts.simf b/simf/asserts.simf new file mode 100644 index 0000000..a95ba99 --- /dev/null +++ b/simf/asserts.simf @@ -0,0 +1,57 @@ +/// Asserts that two u8 are equal +pub fn assert_eq8(a: u8, b: u8) { + assert!(jet::eq_8(a, b)); +} + +/// Asserts that two u16 are equal +pub fn assert_eq16(a: u16, b: u16) { + assert!(jet::eq_16(a, b)); +} + +/// Asserts that two u32 are equal +pub fn assert_eq32(a: u32, b: u32) { + assert!(jet::eq_32(a, b)); +} + +/// Asserts that two u64 are equal +pub fn assert_eq64(a: u64, b: u64) { + assert!(jet::eq_64(a, b)); +} + +/// Asserts that two u256 are equal +pub fn assert_eq256(a: u256, b: u256) { + assert!(jet::eq_256(a, b)); +} + +/// Asserts that provided u8 Option value is a None +pub fn assert_none8(val: Option) { + assert!(is_none::(val)); +} + +/// Asserts that provided u16 Option value is a None +pub fn assert_none16(val: Option) { + assert!(is_none::(val)); +} + +/// Asserts that provided u32 Option value is a None +pub fn assert_none32(val: Option) { + assert!(is_none::(val)); +} + +/// Asserts that provided u64 Option value is a None +pub fn assert_none64(val: Option) { + assert!(is_none::(val)); +} + +/// Asserts that provided u128 Option value is a None +pub fn assert_none128(val: Option) { + assert!(is_none::(val)); +} + +/// Asserts that provided u256 Option value is a None +pub fn assert_none256(val: Option) { + assert!(is_none::(val)); +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/simf/mock/asserts_mock.simf b/simf/mock/asserts_mock.simf new file mode 100644 index 0000000..f6644eb --- /dev/null +++ b/simf/mock/asserts_mock.simf @@ -0,0 +1,66 @@ +// todo: switch to function import when available + +pub fn assert_eq8(a: u8, b: u8) { + assert!(jet::eq_8(a, b)); +} + +pub fn assert_eq16(a: u16, b: u16) { + assert!(jet::eq_16(a, b)); +} + +pub fn assert_eq32(a: u32, b: u32) { + assert!(jet::eq_32(a, b)); +} + +pub fn assert_eq64(a: u64, b: u64) { + assert!(jet::eq_64(a, b)); +} + +pub fn assert_eq256(a: u256, b: u256) { + assert!(jet::eq_256(a, b)); +} + +pub fn assert_none8(val: Option) { + assert!(is_none::(val)); +} + +pub fn assert_none16(val: Option) { + assert!(is_none::(val)); +} + +pub fn assert_none32(val: Option) { + assert!(is_none::(val)); +} + +pub fn assert_none64(val: Option) { + assert!(is_none::(val)); +} + +pub fn assert_none128(val: Option) { + assert!(is_none::(val)); +} + +pub fn assert_none256(val: Option) { + assert!(is_none::(val)); +} + +fn main() { + let some_u8: u8 = 255; + let some_u16: u16 = 65535; + let some_u32: u32 = 4294967295; + let some_u64: u64 = 18446744073709551615; + let some_u256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + assert_eq8(some_u8, some_u8); + assert_eq16(some_u16, some_u16); + assert_eq32(some_u32, some_u32); + assert_eq64(some_u64, some_u64); + assert_eq256(some_u256, some_u256); + + assert_none8(None); + assert_none16(None); + assert_none32(None); + assert_none64(None); + assert_none128(None); + assert_none256(None); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..91946c7 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod artifacts; diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs new file mode 100644 index 0000000..1091943 --- /dev/null +++ b/tests/asserts_test.rs @@ -0,0 +1,59 @@ +use simplex::simplicityhl::elements::{Script}; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::asserts_mock::AssertsMockProgram; +use simplicityhl_std::artifacts::mock::asserts_mock::derived_asserts_mock::{AssertsMockWitness, AssertsMockArguments}; + +fn get_asserts_test_script(context: &simplex::TestContext) -> (AssertsMockProgram, Script) { + let arguments = AssertsMockArguments {}; + + let asserts_program = AssertsMockProgram::new(arguments); + + let asserts_script = asserts_program.get_script_pubkey(context.get_network()); + + (asserts_program, asserts_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, asserts_script) = get_asserts_test_script(context); + + let tx_receipt = signer.send(asserts_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (asserts_program, asserts_script) = get_asserts_test_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&asserts_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = AssertsMockWitness {}; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new(Box::new(asserts_program.as_ref().clone()), Box::new(witness.clone())), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn asserts_test(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script(&context)?; + + Ok(()) +} From 03b5ba7b58d8d42502394dc898d3f04feca5315c Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Sat, 30 May 2026 22:10:13 +0300 Subject: [PATCH 02/13] Example of a test with the unhappy path (#9) * updated test with negative path for asserts * fixed typo * added helper function to mock; fixed typo * added more specific error check --- simf/mock/asserts_mock.simf | 114 +++++++++++++++---- tests/asserts_test.rs | 219 +++++++++++++++++++++++++++++++++++- 2 files changed, 305 insertions(+), 28 deletions(-) diff --git a/simf/mock/asserts_mock.simf b/simf/mock/asserts_mock.simf index f6644eb..f20b8c8 100644 --- a/simf/mock/asserts_mock.simf +++ b/simf/mock/asserts_mock.simf @@ -1,66 +1,132 @@ // todo: switch to function import when available - -pub fn assert_eq8(a: u8, b: u8) { +pub fn assert_eq8(a: u8, b: u8) { // 1 assert!(jet::eq_8(a, b)); } -pub fn assert_eq16(a: u16, b: u16) { +pub fn assert_eq16(a: u16, b: u16) { // 2 assert!(jet::eq_16(a, b)); } -pub fn assert_eq32(a: u32, b: u32) { +pub fn assert_eq32(a: u32, b: u32) { // 3 assert!(jet::eq_32(a, b)); } -pub fn assert_eq64(a: u64, b: u64) { +pub fn assert_eq64(a: u64, b: u64) { // 4 assert!(jet::eq_64(a, b)); } -pub fn assert_eq256(a: u256, b: u256) { +pub fn assert_eq256(a: u256, b: u256) { // 5 assert!(jet::eq_256(a, b)); } -pub fn assert_none8(val: Option) { +pub fn assert_none8(val: Option) { // 6 assert!(is_none::(val)); } -pub fn assert_none16(val: Option) { +pub fn assert_none16(val: Option) { // 7 assert!(is_none::(val)); } -pub fn assert_none32(val: Option) { +pub fn assert_none32(val: Option) { // 8 assert!(is_none::(val)); } -pub fn assert_none64(val: Option) { +pub fn assert_none64(val: Option) { // 9 assert!(is_none::(val)); } -pub fn assert_none128(val: Option) { +pub fn assert_none128(val: Option) { // 10 assert!(is_none::(val)); } -pub fn assert_none256(val: Option) { +pub fn assert_none256(val: Option) { // 11 assert!(is_none::(val)); } +fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} + fn main() { + let flag: u8 = witness::FLAG; + let ifHappyPath: bool = if_test_this_function(0, flag); + let some_u8: u8 = 255; let some_u16: u16 = 65535; let some_u32: u32 = 4294967295; let some_u64: u64 = 18446744073709551615; + let some_u128: u128 = 340282366920938463463374607431768211455; let some_u256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - assert_eq8(some_u8, some_u8); - assert_eq16(some_u16, some_u16); - assert_eq32(some_u32, some_u32); - assert_eq64(some_u64, some_u64); - assert_eq256(some_u256, some_u256); - - assert_none8(None); - assert_none16(None); - assert_none32(None); - assert_none64(None); - assert_none128(None); - assert_none256(None); + match ifHappyPath { + true => { + assert_eq8(some_u8, some_u8); + assert_eq16(some_u16, some_u16); + assert_eq32(some_u32, some_u32); + assert_eq64(some_u64, some_u64); + assert_eq256(some_u256, some_u256); + + assert_none8(None); + assert_none16(None); + assert_none32(None); + assert_none64(None); + assert_none128(None); + assert_none256(None); + }, false => { + match if_test_this_function(1, flag) { + true => assert_eq8(1, 2), + false => (), + }; + + match if_test_this_function(2, flag) { + true => assert_eq16(1, 2), + false => (), + }; + + match if_test_this_function(3, flag) { + true => assert_eq32(1, 2), + false => (), + }; + + match if_test_this_function(4, flag) { + true => assert_eq64(1, 2), + false => (), + }; + + match if_test_this_function(5, flag) { + true => assert_eq256(1, 2), + false => (), + }; + + match if_test_this_function(6, flag) { + true => assert_none8(Some(some_u8)), + false => (), + }; + + match if_test_this_function(7, flag) { + true => assert_none16(Some(some_u16)), + false => (), + }; + + match if_test_this_function(8, flag) { + true => assert_none32(Some(some_u32)), + false => (), + }; + + match if_test_this_function(9, flag) { + true => assert_none64(Some(some_u64)), + false => (), + }; + + match if_test_this_function(10, flag) { + true => assert_none128(Some(some_u128)), + false => (), + }; + + match if_test_this_function(11, flag) { + true => assert_none256(Some(some_u256)), + false => (), + }; + } + } } diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index 1091943..468340c 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -26,7 +26,7 @@ fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { Ok(()) } -fn spend_script(context: &simplex::TestContext) -> anyhow::Result<()> { +fn spend_script(context: &simplex::TestContext, flag: u8) -> anyhow::Result<()> { let signer = context.get_default_signer(); let provider = context.get_default_provider(); @@ -36,7 +36,7 @@ fn spend_script(context: &simplex::TestContext) -> anyhow::Result<()> { let mut ft = FinalTransaction::new(); - let witness = AssertsMockWitness {}; + let witness = AssertsMockWitness {flag: flag}; ft.add_program_input( PartialInput::new(asserts_utxos[0].clone()), @@ -51,9 +51,220 @@ fn spend_script(context: &simplex::TestContext) -> anyhow::Result<()> { } #[simplex::test] -fn asserts_test(context: simplex::TestContext) -> anyhow::Result<()> { +fn asserts_test_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 0; + + fund_script(&context)?; + spend_script(&context, flag)?; + + Ok(()) +} + +#[simplex::test] +fn assert_eq8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 1; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_eq16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 2; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_eq32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 3; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_eq64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 4; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_eq256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 5; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 6; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 7; + fund_script(&context)?; - spend_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 8; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 9; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 10; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); + + Ok(()) +} + +#[simplex::test] +fn assert_none256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + let flag: u8 = 11; + + fund_script(&context)?; + + let txid_result = spend_script(&context, flag); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert_eq!(err, "Failed to prune program: Jet failed during execution"); Ok(()) } From e40d9fb4e4928c874f8d8213bec9c29d77cc3fcc Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:13:10 +0300 Subject: [PATCH 03/13] Updated smplx version (#12) * updated minimal simplex version to 0.0.6 * fixed test command in ci --- .github/workflows/tests.yml | 2 +- Cargo.lock | 171 +++++++++++++++++------------------- Cargo.toml | 2 +- 3 files changed, 81 insertions(+), 94 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 03a6a52..2178d4a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -58,4 +58,4 @@ jobs: - name: Test run: | - simplex test --nocapture + simplex test -v diff --git a/Cargo.lock b/Cargo.lock index 367e18e..97599e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "ar_archive_writer" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348" dependencies = [ "object", ] @@ -90,17 +90,16 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base58ck" -version = "0.1.0" +version = "0.1.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +checksum = "ec5dc7e09f7bb15f0062da7c03086d6b71a2c84e0af4fccbbc7d8c6559847816" dependencies = [ - "bitcoin-internals", "bitcoin_hashes", ] @@ -137,14 +136,13 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.32.9" +version = "0.32.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf93e61f2dbc3e3c41234ca26a65e2c0b0975c52e0f069ab9893ebbede584d3" +checksum = "39581299241111285f3268ba75ddf372746fd041620918b145c1af9d75e91b6c" dependencies = [ "base58ck", "base64 0.21.7", "bech32", - "bitcoin-internals", "bitcoin-io", "bitcoin-units", "bitcoin_hashes", @@ -154,20 +152,11 @@ dependencies = [ "serde", ] -[[package]] -name = "bitcoin-internals" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" -dependencies = [ - "serde", -] - [[package]] name = "bitcoin-io" -version = "0.1.4" +version = "0.1.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" +checksum = "11301df0b06f22dea7bb1916403fdd88a371031e495c49b8f96931b28189e175" [[package]] name = "bitcoin-private" @@ -177,19 +166,18 @@ checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" [[package]] name = "bitcoin-units" -version = "0.1.3" +version = "0.1.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118" +checksum = "57bad157b78d0d1b22c4cbb6a35a566211fc4d14866a37f2c780652b50f3b845" dependencies = [ - "bitcoin-internals", "serde", ] [[package]] name = "bitcoin_hashes" -version = "0.14.1" +version = "0.14.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" dependencies = [ "bitcoin-io", "hex-conservative", @@ -241,9 +229,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "block-buffer" @@ -266,9 +254,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byteorder" @@ -278,9 +266,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.62" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "shlex", @@ -402,9 +390,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" dependencies = [ "serde", ] @@ -575,7 +563,7 @@ dependencies = [ "bstr", "log", "regex-automata 0.4.14", - "regex-syntax 0.8.10", + "regex-syntax 0.8.11", ] [[package]] @@ -584,7 +572,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "ignore", "walkdir", ] @@ -659,9 +647,9 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "ignore" -version = "0.4.25" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +checksum = "b915661dd01db3f05050265b2477bcc6527b3792388e2749b41623cc592be67d" dependencies = [ "crossbeam-deque", "globset", @@ -708,13 +696,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -756,15 +743,15 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "log" -version = "0.4.29" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memoffset" @@ -777,9 +764,9 @@ dependencies = [ [[package]] name = "miniscript" -version = "12.3.6" +version = "12.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c14116d8342edd3626b0f8e84df16f4e6a76dc04799ba747493403236a1b8ac5" +checksum = "b8343cc1ef1408bd9bdbf69f7aef47017dfab7e6349ec26fddf62e0e9fb5a4cf" dependencies = [ "bech32", "bitcoin", @@ -936,14 +923,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.14", - "regex-syntax 0.8.10", + "regex-syntax 0.8.11", ] [[package]] @@ -965,7 +952,7 @@ checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.10", + "regex-syntax 0.8.11", ] [[package]] @@ -976,9 +963,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "ring" @@ -1000,7 +987,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -1013,7 +1000,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -1158,9 +1145,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -1191,9 +1178,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simplicity-lang" @@ -1257,9 +1244,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smplx-build" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3170d79eafea8c119d0b491014aaf2054679ba8c285c453c2acb879b52896b5e" +checksum = "bb75724fd0329de24895b58a4010efeeca9773092294845a324aee141ec3c864" dependencies = [ "glob", "globwalk", @@ -1276,9 +1263,9 @@ dependencies = [ [[package]] name = "smplx-macros" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e591d0bb8c971f38ea525b5e1bc18a39b369bc1fdecc07632120142afb7e34" +checksum = "4777f6ff9a27faf98396181d67f04f720e0c472c2a3f1db76c5475b45da8963f" dependencies = [ "smplx-build", "smplx-test", @@ -1287,9 +1274,9 @@ dependencies = [ [[package]] name = "smplx-regtest" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b42c1ad54f123195eb90543e88a2e3b1519a11479862ac29a5cd7a0e24f13d7" +checksum = "bf3711284f8ad7859ae0605841e90316bdf41be5b09011639e765667f07feb5d" dependencies = [ "electrsd", "hex", @@ -1303,9 +1290,9 @@ dependencies = [ [[package]] name = "smplx-sdk" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe05e7d0f9cef029968453f087f323df01f92e13fc240796a732cffac734074a" +checksum = "c96c7de4f86f4a74dc4c910d6d0541d63cd661e3f616566054a36e589ffcda2c" dependencies = [ "bip39", "bitcoin_hashes", @@ -1323,9 +1310,9 @@ dependencies = [ [[package]] name = "smplx-std" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8465bd3dae0d1bf37c88f2ba4144e5b5157d390a3c5e56016ff04b64ee9fc199" +checksum = "38cef91f2523cfb6e8937bb1c8004869d539e0dcd8c62fef68c93cc3a6233117" dependencies = [ "either", "serde", @@ -1337,9 +1324,9 @@ dependencies = [ [[package]] name = "smplx-test" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1025e34b6101ab8e92b6baa4807227894ca324e0405d22a703c2ddd6c5af979" +checksum = "c9c8878fae6868b9fbf7ed7cb3e261dc308b55ea418bb4421685dad99f98fc1f" dependencies = [ "electrsd", "proc-macro2", @@ -1467,7 +1454,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -1478,9 +1465,9 @@ checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" @@ -1499,9 +1486,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-xid" @@ -1563,9 +1550,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" dependencies = [ "cfg-if", "once_cell", @@ -1576,9 +1563,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1586,9 +1573,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" dependencies = [ "bumpalo", "proc-macro2", @@ -1599,9 +1586,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" dependencies = [ "unicode-ident", ] @@ -1634,7 +1621,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -1772,9 +1759,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" [[package]] name = "winnow" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" [[package]] name = "wit-bindgen" @@ -1840,7 +1827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.1", + "bitflags 2.13.0", "indexmap", "log", "serde", @@ -1872,18 +1859,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 030390b..074643e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,6 @@ rust-version = "1.91.0" version = "0.1.0" [dependencies] -smplx-std = { version = ">=0.0.5, <0.1.0" } +smplx-std = { version = ">=0.0.6, <0.1.0" } anyhow = { version = "1.0.101" } From 588d91eee69670c91675aec917ff1beb5b82d867 Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Mon, 15 Jun 2026 15:47:13 +0300 Subject: [PATCH 04/13] Asserts function refactoring (#11) * renamed asserts functions to be more consistent; removed unsuported "pub" modifier * made asserts test more detailed; added random generation of test data --- Cargo.lock | 1 + Cargo.toml | 1 + simf/asserts.simf | 24 ++- simf/mock/asserts_mock.simf | 196 ++++++++++-------- tests/asserts_test.rs | 399 ++++++++++++++++++++++++++++++++---- tests/helper.rs | 32 +++ 6 files changed, 509 insertions(+), 144 deletions(-) create mode 100644 tests/helper.rs diff --git a/Cargo.lock b/Cargo.lock index 97599e2..c59c2ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1233,6 +1233,7 @@ name = "simplicityhl_std" version = "0.1.0" dependencies = [ "anyhow", + "rand", "smplx-std", ] diff --git a/Cargo.toml b/Cargo.toml index 074643e..c2cd2be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ version = "0.1.0" smplx-std = { version = ">=0.0.6, <0.1.0" } anyhow = { version = "1.0.101" } +rand = { version = "0.8.6" } diff --git a/simf/asserts.simf b/simf/asserts.simf index a95ba99..7707a59 100644 --- a/simf/asserts.simf +++ b/simf/asserts.simf @@ -1,55 +1,57 @@ /// Asserts that two u8 are equal -pub fn assert_eq8(a: u8, b: u8) { +fn assert_eq_8(a: u8, b: u8) { assert!(jet::eq_8(a, b)); } /// Asserts that two u16 are equal -pub fn assert_eq16(a: u16, b: u16) { +fn assert_eq_16(a: u16, b: u16) { assert!(jet::eq_16(a, b)); } /// Asserts that two u32 are equal -pub fn assert_eq32(a: u32, b: u32) { +fn assert_eq_32(a: u32, b: u32) { assert!(jet::eq_32(a, b)); } /// Asserts that two u64 are equal -pub fn assert_eq64(a: u64, b: u64) { +fn assert_eq_64(a: u64, b: u64) { assert!(jet::eq_64(a, b)); } +// todo: assert_eq_128 + /// Asserts that two u256 are equal -pub fn assert_eq256(a: u256, b: u256) { +fn assert_eq_256(a: u256, b: u256) { assert!(jet::eq_256(a, b)); } /// Asserts that provided u8 Option value is a None -pub fn assert_none8(val: Option) { +fn assert_none_8(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u16 Option value is a None -pub fn assert_none16(val: Option) { +fn assert_none_16(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u32 Option value is a None -pub fn assert_none32(val: Option) { +fn assert_none_32(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u64 Option value is a None -pub fn assert_none64(val: Option) { +fn assert_none_64(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u128 Option value is a None -pub fn assert_none128(val: Option) { +fn assert_none_128(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u256 Option value is a None -pub fn assert_none256(val: Option) { +fn assert_none_256(val: Option) { assert!(is_none::(val)); } diff --git a/simf/mock/asserts_mock.simf b/simf/mock/asserts_mock.simf index f20b8c8..fe2fb62 100644 --- a/simf/mock/asserts_mock.simf +++ b/simf/mock/asserts_mock.simf @@ -1,132 +1,150 @@ // todo: switch to function import when available -pub fn assert_eq8(a: u8, b: u8) { // 1 +fn assert_eq_8(a: u8, b: u8) { // 0 assert!(jet::eq_8(a, b)); } -pub fn assert_eq16(a: u16, b: u16) { // 2 +fn assert_eq_16(a: u16, b: u16) { // 1 assert!(jet::eq_16(a, b)); } -pub fn assert_eq32(a: u32, b: u32) { // 3 +fn assert_eq_32(a: u32, b: u32) { // 2 assert!(jet::eq_32(a, b)); } -pub fn assert_eq64(a: u64, b: u64) { // 4 +fn assert_eq_64(a: u64, b: u64) { // 3 assert!(jet::eq_64(a, b)); } -pub fn assert_eq256(a: u256, b: u256) { // 5 +// todo: assert_eq_128 + +fn assert_eq_256(a: u256, b: u256) { // 4 assert!(jet::eq_256(a, b)); } -pub fn assert_none8(val: Option) { // 6 +fn assert_none_8(val: Option) { // 5 assert!(is_none::(val)); } -pub fn assert_none16(val: Option) { // 7 +fn assert_none_16(val: Option) { // 6 assert!(is_none::(val)); } -pub fn assert_none32(val: Option) { // 8 +fn assert_none_32(val: Option) { // 7 assert!(is_none::(val)); } -pub fn assert_none64(val: Option) { // 9 +fn assert_none_64(val: Option) { // 8 assert!(is_none::(val)); } -pub fn assert_none128(val: Option) { // 10 +fn assert_none_128(val: Option) { // 9 assert!(is_none::(val)); } -pub fn assert_none256(val: Option) { // 11 +fn assert_none_256(val: Option) { // 10 assert!(is_none::(val)); } +// helper fn if_test_this_function(index: u8, flag: u8) -> bool { jet::eq_8(index, flag) } fn main() { - let flag: u8 = witness::FLAG; - let ifHappyPath: bool = if_test_this_function(0, flag); + let function_index: u8 = witness::FUNCTION_INDEX; + + let first_arg_u8: Option = witness::FIRST_ARG_U8; + let second_arg_u8: Option = witness::SECOND_ARG_U8; + + let first_arg_u16: Option = witness::FIRST_ARG_U16; + let second_arg_u16: Option = witness::SECOND_ARG_U16; + + let first_arg_u32: Option = witness::FIRST_ARG_U32; + let second_arg_u32: Option = witness::SECOND_ARG_U32; + + let first_arg_u64: Option = witness::FIRST_ARG_U64; + let second_arg_u64: Option = witness::SECOND_ARG_U64; - let some_u8: u8 = 255; - let some_u16: u16 = 65535; - let some_u32: u32 = 4294967295; - let some_u64: u64 = 18446744073709551615; - let some_u128: u128 = 340282366920938463463374607431768211455; - let some_u256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + let first_arg_u128: Option = witness::FIRST_ARG_U128; + let second_arg_u128: Option = witness::SECOND_ARG_U128; + + let first_arg_u256: Option = witness::FIRST_ARG_U256; + let second_arg_u256: Option = witness::SECOND_ARG_U256; + + match if_test_this_function(0, function_index) { + true => { + assert_eq_8(unwrap(first_arg_u8), unwrap(second_arg_u8)); + }, + false => (), + }; + + match if_test_this_function(1, function_index) { + true => { + assert_eq_16(unwrap(first_arg_u16), unwrap(second_arg_u16)); + }, + false => (), + }; + + match if_test_this_function(2, function_index) { + true => { + assert_eq_32(unwrap(first_arg_u32), unwrap(second_arg_u32)); + }, + false => (), + }; + + match if_test_this_function(3, function_index) { + true => { + assert_eq_64(unwrap(first_arg_u64), unwrap(second_arg_u64)); + }, + false => (), + }; + + match if_test_this_function(4, function_index) { + true => { + assert_eq_256(unwrap(first_arg_u256), unwrap(second_arg_u256)); + }, + false => (), + }; + + match if_test_this_function(5, function_index) { + true => { + assert_none_8(first_arg_u8); + }, + false => (), + }; + + match if_test_this_function(6, function_index) { + true => { + assert_none_16(first_arg_u16); + }, + false => (), + }; + + match if_test_this_function(7, function_index) { + true => { + assert_none_32(first_arg_u32); + }, + false => (), + }; + + match if_test_this_function(8, function_index) { + true => { + assert_none_64(first_arg_u64); + }, + false => (), + }; + + match if_test_this_function(9, function_index) { + true => { + assert_none_128(first_arg_u128); + }, + false => (), + }; - match ifHappyPath { + match if_test_this_function(10, function_index) { true => { - assert_eq8(some_u8, some_u8); - assert_eq16(some_u16, some_u16); - assert_eq32(some_u32, some_u32); - assert_eq64(some_u64, some_u64); - assert_eq256(some_u256, some_u256); - - assert_none8(None); - assert_none16(None); - assert_none32(None); - assert_none64(None); - assert_none128(None); - assert_none256(None); - }, false => { - match if_test_this_function(1, flag) { - true => assert_eq8(1, 2), - false => (), - }; - - match if_test_this_function(2, flag) { - true => assert_eq16(1, 2), - false => (), - }; - - match if_test_this_function(3, flag) { - true => assert_eq32(1, 2), - false => (), - }; - - match if_test_this_function(4, flag) { - true => assert_eq64(1, 2), - false => (), - }; - - match if_test_this_function(5, flag) { - true => assert_eq256(1, 2), - false => (), - }; - - match if_test_this_function(6, flag) { - true => assert_none8(Some(some_u8)), - false => (), - }; - - match if_test_this_function(7, flag) { - true => assert_none16(Some(some_u16)), - false => (), - }; - - match if_test_this_function(8, flag) { - true => assert_none32(Some(some_u32)), - false => (), - }; - - match if_test_this_function(9, flag) { - true => assert_none64(Some(some_u64)), - false => (), - }; - - match if_test_this_function(10, flag) { - true => assert_none128(Some(some_u128)), - false => (), - }; - - match if_test_this_function(11, flag) { - true => assert_none256(Some(some_u256)), - false => (), - }; - } - } + assert_none_256(first_arg_u256); + }, + false => (), + }; } diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index 468340c..b593cee 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -1,9 +1,44 @@ -use simplex::simplicityhl::elements::{Script}; +use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; use simplicityhl_std::artifacts::mock::asserts_mock::AssertsMockProgram; -use simplicityhl_std::artifacts::mock::asserts_mock::derived_asserts_mock::{AssertsMockWitness, AssertsMockArguments}; +use simplicityhl_std::artifacts::mock::asserts_mock::derived_asserts_mock::{ + AssertsMockArguments, AssertsMockWitness, +}; + +mod helper; +use crate::helper::{cast_to_bool, generate_uints_in_one_range}; + +enum FunctionToTest { + AssertEq8, + AssertEq16, + AssertEq32, + AssertEq64, + AssertEq256, + AssertNone8, + AssertNone16, + AssertNone32, + AssertNone64, + AssertNone128, + AssertNone256, +} + +const DEFAULT_SOME_U8: Option = Some(0); +const DEFAULT_SOME_U16: Option = Some(0); +const DEFAULT_SOME_U32: Option = Some(0); +const DEFAULT_SOME_U64: Option = Some(0); +const DEFAULT_SOME_U128: Option = Some(0); +const DEFAULT_SOME_U256: Option<[u8; 32]> = Some([0; 32]); + +pub enum IfTestSameValues { + DifferentValues, + SameValues, +} +pub enum IfTestNoneValue { + NotNoneValue, + NoneValue, +} fn get_asserts_test_script(context: &simplex::TestContext) -> (AssertsMockProgram, Script) { let arguments = AssertsMockArguments {}; @@ -23,10 +58,108 @@ fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { let tx_receipt = signer.send(asserts_script.clone(), 50)?; println!("Broadcast: {}", tx_receipt); - Ok(()) + Ok(()) +} + +fn generate_test_witness( + function_index: FunctionToTest, + if_same_values: bool, + if_none_value: bool, +) -> AssertsMockWitness { + let mut witness: AssertsMockWitness = AssertsMockWitness { + function_index: 0, + first_arg_u8: DEFAULT_SOME_U8, + second_arg_u8: DEFAULT_SOME_U8, + first_arg_u16: DEFAULT_SOME_U16, + second_arg_u16: DEFAULT_SOME_U16, + first_arg_u32: DEFAULT_SOME_U32, + second_arg_u32: DEFAULT_SOME_U32, + first_arg_u64: DEFAULT_SOME_U64, + second_arg_u64: DEFAULT_SOME_U64, + first_arg_u128: DEFAULT_SOME_U128, + second_arg_u128: DEFAULT_SOME_U128, + first_arg_u256: DEFAULT_SOME_U256, + second_arg_u256: DEFAULT_SOME_U256, + }; + + match function_index { + FunctionToTest::AssertEq8 => { + let (first_arg, second_arg) = + generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); + + (witness.first_arg_u8, witness.second_arg_u8) = + (Some(first_arg as u8), Some(second_arg as u8)); + } + FunctionToTest::AssertEq16 => { + let (first_arg, second_arg) = + generate_uints_in_one_range(if_same_values, 0, u16::MAX as u128); + + (witness.first_arg_u16, witness.second_arg_u16) = + (Some(first_arg as u16), Some(second_arg as u16)); + } + FunctionToTest::AssertEq32 => { + let (first_arg, second_arg) = + generate_uints_in_one_range(if_same_values, 0, u32::MAX as u128); + + (witness.first_arg_u32, witness.second_arg_u32) = + (Some(first_arg as u32), Some(second_arg as u32)); + } + FunctionToTest::AssertEq64 => { + let (first_arg, second_arg) = + generate_uints_in_one_range(if_same_values, 0, u64::MAX as u128); + + (witness.first_arg_u64, witness.second_arg_u64) = + (Some(first_arg as u64), Some(second_arg as u64)); + } + FunctionToTest::AssertEq256 => { + let (first_arg, second_arg) = + generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); + + (witness.first_arg_u256, witness.second_arg_u256) = + (Some([first_arg as u8; 32]), Some([second_arg as u8; 32])); + } + FunctionToTest::AssertNone8 => { + if if_none_value { + witness.first_arg_u8 = None; + }; + } + FunctionToTest::AssertNone16 => { + if if_none_value { + witness.first_arg_u16 = None; + }; + } + FunctionToTest::AssertNone32 => { + if if_none_value { + witness.first_arg_u32 = None; + }; + } + FunctionToTest::AssertNone64 => { + if if_none_value { + witness.first_arg_u64 = None; + }; + } + FunctionToTest::AssertNone128 => { + if if_none_value { + witness.first_arg_u128 = None; + }; + } + FunctionToTest::AssertNone256 => { + if if_none_value { + witness.first_arg_u256 = None; + }; + } + } + + witness.function_index = function_index as u8; + witness } -fn spend_script(context: &simplex::TestContext, flag: u8) -> anyhow::Result<()> { +fn spend_script( + context: &simplex::TestContext, + function_index: FunctionToTest, + if_same_values: IfTestSameValues, + if_none_value: IfTestNoneValue, +) -> anyhow::Result<()> { let signer = context.get_default_signer(); let provider = context.get_default_provider(); @@ -36,11 +169,18 @@ fn spend_script(context: &simplex::TestContext, flag: u8) -> anyhow::Result<()> let mut ft = FinalTransaction::new(); - let witness = AssertsMockWitness {flag: flag}; + let witness: AssertsMockWitness = generate_test_witness( + function_index, + cast_to_bool(if_same_values as u8), + cast_to_bool(if_none_value as u8), + ); ft.add_program_input( PartialInput::new(asserts_utxos[0].clone()), - ProgramInput::new(Box::new(asserts_program.as_ref().clone()), Box::new(witness.clone())), + ProgramInput::new( + Box::new(asserts_program.as_ref().clone()), + Box::new(witness.clone()), + ), RequiredSignature::None, ); @@ -51,22 +191,28 @@ fn spend_script(context: &simplex::TestContext, flag: u8) -> anyhow::Result<()> } #[simplex::test] -fn asserts_test_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 0; - +fn assert_eq_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - spend_script(&context, flag)?; + spend_script( + &context, + FunctionToTest::AssertEq8, + IfTestSameValues::SameValues, + IfTestNoneValue::NotNoneValue, + )?; Ok(()) } #[simplex::test] -fn assert_eq8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 1; - +fn assert_eq_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertEq8, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -80,12 +226,28 @@ fn assert_eq8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> } #[simplex::test] -fn assert_eq16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 2; +fn assert_eq_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertEq16, + IfTestSameValues::SameValues, + IfTestNoneValue::NotNoneValue, + )?; + + Ok(()) +} +#[simplex::test] +fn assert_eq_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertEq16, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -99,12 +261,28 @@ fn assert_eq16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> } #[simplex::test] -fn assert_eq32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 3; +fn assert_eq_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertEq32, + IfTestSameValues::SameValues, + IfTestNoneValue::NotNoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_eq_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertEq32, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -118,12 +296,28 @@ fn assert_eq32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> } #[simplex::test] -fn assert_eq64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 4; +fn assert_eq_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertEq64, + IfTestSameValues::SameValues, + IfTestNoneValue::NotNoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_eq_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertEq64, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -137,12 +331,28 @@ fn assert_eq64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> } #[simplex::test] -fn assert_eq256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 5; +fn assert_eq_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertEq256, + IfTestSameValues::SameValues, + IfTestNoneValue::NotNoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_eq_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertEq256, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -156,12 +366,28 @@ fn assert_eq256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<() } #[simplex::test] -fn assert_none8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 6; +fn assert_none_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertNone8, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_none_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone8, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -175,12 +401,29 @@ fn assert_none8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<() } #[simplex::test] -fn assert_none16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 7; +fn assert_none_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + + spend_script( + &context, + FunctionToTest::AssertNone16, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_none_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone16, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -194,12 +437,29 @@ fn assert_none16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<( } #[simplex::test] -fn assert_none32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 8; +fn assert_none_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + + spend_script( + &context, + FunctionToTest::AssertNone32, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + + Ok(()) +} +#[simplex::test] +fn assert_none_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone32, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -213,12 +473,29 @@ fn assert_none32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<( } #[simplex::test] -fn assert_none64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 9; +fn assert_none_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + + spend_script( + &context, + FunctionToTest::AssertNone64, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + Ok(()) +} + +#[simplex::test] +fn assert_none_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone64, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -232,12 +509,29 @@ fn assert_none64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<( } #[simplex::test] -fn assert_none128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 10; +fn assert_none_128_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + + spend_script( + &context, + FunctionToTest::AssertNone128, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + + Ok(()) +} +#[simplex::test] +fn assert_none_128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone128, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), @@ -251,12 +545,29 @@ fn assert_none128_unhappy_path(context: simplex::TestContext) -> anyhow::Result< } #[simplex::test] -fn assert_none256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - let flag: u8 = 11; +fn assert_none_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::AssertNone256, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NoneValue, + )?; + + Ok(()) +} + +#[simplex::test] +fn assert_none_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { fund_script(&context)?; - let txid_result = spend_script(&context, flag); + let txid_result = spend_script( + &context, + FunctionToTest::AssertNone256, + IfTestSameValues::DifferentValues, + IfTestNoneValue::NotNoneValue, + ); assert!( txid_result.is_err(), diff --git a/tests/helper.rs b/tests/helper.rs new file mode 100644 index 0000000..b714244 --- /dev/null +++ b/tests/helper.rs @@ -0,0 +1,32 @@ +use rand::Rng; + +#[allow(dead_code)] +pub enum IfTestOverflow { + NotOverflow, + Overflow, +} + +pub fn cast_to_bool(flag: u8) -> bool { + flag == 1 +} + +#[allow(dead_code)] +pub fn generate_uints_in_one_range(if_same: bool, min_val: u128, max_val: u128) -> (u128, u128) { + let some_u = rand::thread_rng().gen_range(min_val..=max_val); + + if if_same { + (some_u, some_u) + } else { + if min_val == max_val { + panic!("Can not generate different values when range is one number"); + } + + let mut other_u = rand::thread_rng().gen_range(min_val..=max_val); + + while other_u == some_u { + other_u = rand::thread_rng().gen_range(min_val..=max_val); + } + + (some_u, other_u) + } +} From 1a9f16c0d430efd94ec50d35b29a3b5979d494c8 Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:12:36 +0300 Subject: [PATCH 05/13] added logical operations (#13) --- simf/logical_operations.simf | 17 +++++++ simf/mock/logical_operations_mock.simf | 27 +++++++++++ tests/logical_operations_test.rs | 65 ++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 simf/logical_operations.simf create mode 100644 simf/mock/logical_operations_mock.simf create mode 100644 tests/logical_operations_test.rs diff --git a/simf/logical_operations.simf b/simf/logical_operations.simf new file mode 100644 index 0000000..a8b94de --- /dev/null +++ b/simf/logical_operations.simf @@ -0,0 +1,17 @@ +/// Returns the result of the NOT operation on the provided value +fn not(bit: bool) -> bool { + ::into(jet::complement_1(::into(bit))) +} + +/// Returns the result of the OR operation on the provided values +fn or(a: bool, b: bool) -> bool { + ::into(jet::or_1(::into(a), ::into(b))) +} + +/// Returns the result of the AND operation on the provided values +fn and(a: bool, b: bool) -> bool { + ::into(jet::and_1(::into(a), ::into(b))) +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/simf/mock/logical_operations_mock.simf b/simf/mock/logical_operations_mock.simf new file mode 100644 index 0000000..4ab4e22 --- /dev/null +++ b/simf/mock/logical_operations_mock.simf @@ -0,0 +1,27 @@ +// todo: switch to function import when available +fn not(bit: bool) -> bool { + ::into(jet::complement_1(::into(bit))) +} + +fn or(a: bool, b: bool) -> bool { + ::into(jet::or_1(::into(a), ::into(b))) +} + +fn and(a: bool, b: bool) -> bool { + ::into(jet::and_1(::into(a), ::into(b))) +} + +fn main() { + assert!(not(false)); + assert!(not((not(true)))); + + assert!(or(true, false)); + assert!(or(false, true)); + assert!(or(true, true)); + assert!(not(or(false, false))); + + assert!(and(true, true)); + assert!(not(and(true, false))); + assert!(not(and(false, true))); + assert!(not(and(false, false))); +} diff --git a/tests/logical_operations_test.rs b/tests/logical_operations_test.rs new file mode 100644 index 0000000..035211d --- /dev/null +++ b/tests/logical_operations_test.rs @@ -0,0 +1,65 @@ +use simplex::simplicityhl::elements::Script; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::logical_operations_mock::LogicalOperationsMockProgram; +use simplicityhl_std::artifacts::mock::logical_operations_mock::derived_logical_operations_mock::{ + LogicalOperationsMockArguments, LogicalOperationsMockWitness, +}; + +fn get_script(context: &simplex::TestContext) -> (LogicalOperationsMockProgram, Script) { + let arguments = LogicalOperationsMockArguments {}; + + let logical_operations_program = LogicalOperationsMockProgram::new(arguments); + + let logical_operations_script = + logical_operations_program.get_script_pubkey(context.get_network()); + + (logical_operations_program, logical_operations_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, logical_operations_script) = get_script(context); + + let tx_receipt = signer.send(logical_operations_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (logical_operations_program, logical_operations_script) = get_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&logical_operations_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = LogicalOperationsMockWitness {}; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new( + Box::new(logical_operations_program.as_ref().clone()), + Box::new(witness.clone()), + ), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn logical_operations_test(context: simplex::TestContext) -> anyhow::Result<()> { + fund_script(&context)?; + spend_script(&context)?; + + Ok(()) +} From 48ba803cb250682c64c5312c0a090e4e74436046 Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:19:45 +0300 Subject: [PATCH 06/13] Added safe uint functions (#14) * added safe functions for u8, u16, u32, u64 * added mocks and tests for uints * fixed incorrect names in tests * fixed import order in tests * linting * refactored error assertion in tests --- simf/mock/u16_mock.simf | 194 ++++++++++++++++++ simf/mock/u32_mock.simf | 194 ++++++++++++++++++ simf/mock/u64_mock.simf | 194 ++++++++++++++++++ simf/mock/u8_mock.simf | 194 ++++++++++++++++++ simf/u16.simf | 62 ++++++ simf/u32.simf | 62 ++++++ simf/u64.simf | 62 ++++++ simf/u8.simf | 62 ++++++ tests/asserts_test.rs | 1 + tests/u16_test.rs | 426 ++++++++++++++++++++++++++++++++++++++++ tests/u32_test.rs | 426 ++++++++++++++++++++++++++++++++++++++++ tests/u64_test.rs | 426 ++++++++++++++++++++++++++++++++++++++++ tests/u8_test.rs | 424 +++++++++++++++++++++++++++++++++++++++ 13 files changed, 2727 insertions(+) create mode 100644 simf/mock/u16_mock.simf create mode 100644 simf/mock/u32_mock.simf create mode 100644 simf/mock/u64_mock.simf create mode 100644 simf/mock/u8_mock.simf create mode 100644 simf/u16.simf create mode 100644 simf/u32.simf create mode 100644 simf/u64.simf create mode 100644 simf/u8.simf create mode 100644 tests/u16_test.rs create mode 100644 tests/u32_test.rs create mode 100644 tests/u64_test.rs create mode 100644 tests/u8_test.rs diff --git a/simf/mock/u16_mock.simf b/simf/mock/u16_mock.simf new file mode 100644 index 0000000..ff893d4 --- /dev/null +++ b/simf/mock/u16_mock.simf @@ -0,0 +1,194 @@ +// todo: switch to function import when available +fn checked_add_16(a: u16, b: u16) -> Option { + let (carry, sum): (bool, u16) = jet::add_16(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +fn safe_add_16(a: u16, b: u16) -> u16 { + unwrap(checked_add_16(a, b)) +} + +fn checked_sub_16(a: u16, b: u16) -> Option { + let (borrow, diff): (bool, u16) = jet::subtract_16(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +fn safe_sub_16(a: u16, b: u16) -> u16 { + unwrap(checked_sub_16(a, b)) +} + +fn checked_mul_16(a: u16, b: u16) -> Option { + let result: u32 = jet::multiply_16(a, b); + + let (high, low): (u16, u16) = ::into(result); + + match jet::is_zero_16(high) { + true => Some(low), + false => None, + } +} + +fn safe_mul_16(a: u16, b: u16) -> u16 { + unwrap(checked_mul_16(a, b)) +} + +fn checked_div_16(a: u16, b: u16) -> Option { + match jet::is_zero_16(b) { + true => None, + false => Some(jet::divide_16(a, b)), + } +} + +fn safe_div_16(a: u16, b: u16) -> u16 { + unwrap(checked_div_16(a, b)) +} + +// helper +fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} + +fn main() { + let function_index: u8 = witness::FUNCTION_INDEX; + let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; + + let first_arg: u16 = witness::FIRST_ARG; + let second_arg: u16 = witness::SECOND_ARG; + let result: u16 = witness::RESULT; + + // add + match if_test_this_function(0, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: Option = checked_add_16(first_arg, second_arg); + assert!(is_none::(overflowing_u16)); + }, + false => { + let fitting_u16: Option = checked_add_16(first_arg, second_arg); + assert!(jet::eq_16(unwrap(fitting_u16), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(1, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: u16 = safe_add_16(first_arg, second_arg); + }, + false => { + let fitting_u16: u16 = safe_add_16(first_arg, second_arg); + assert!(jet::eq_16(fitting_u16, result)); + } + } + }, + false => (), + }; + + // subtract + match if_test_this_function(2, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: Option = checked_sub_16(first_arg, second_arg); + assert!(is_none::(overflowing_u16)); + }, + false => { + let fitting_u16: Option = checked_sub_16(first_arg, second_arg); + assert!(jet::eq_16(unwrap(fitting_u16), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(3, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: u16 = safe_sub_16(first_arg, second_arg); + }, + false => { + let fitting_u16: u16 = safe_sub_16(first_arg, second_arg); + assert!(jet::eq_16(fitting_u16, result)); + } + } + }, + false => (), + }; + + // multiply + match if_test_this_function(4, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: Option = checked_mul_16(first_arg, second_arg); + assert!(is_none::(overflowing_u16)); + }, + false => { + let fitting_u16: Option = checked_mul_16(first_arg, second_arg); + assert!(jet::eq_16(unwrap(fitting_u16), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(5, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: u16 = safe_mul_16(first_arg, second_arg); + }, + false => { + let fitting_u16: u16 = safe_mul_16(first_arg, second_arg); + assert!(jet::eq_16(fitting_u16, result)); + } + } + }, + false => (), + }; + + // divide + match if_test_this_function(6, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: Option = checked_div_16(first_arg, second_arg); + assert!(is_none::(overflowing_u16)); + }, + false => { + let fitting_u16: Option = checked_div_16(first_arg, second_arg); + assert!(jet::eq_16(unwrap(fitting_u16), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(7, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u16: u16 = safe_div_16(first_arg, second_arg); + }, + false => { + let fitting_u16: u16 = safe_div_16(first_arg, second_arg); + assert!(jet::eq_16(fitting_u16, result)); + } + } + }, + false => (), + }; +} diff --git a/simf/mock/u32_mock.simf b/simf/mock/u32_mock.simf new file mode 100644 index 0000000..2c14b28 --- /dev/null +++ b/simf/mock/u32_mock.simf @@ -0,0 +1,194 @@ +// todo: switch to function import when available +fn checked_add_32(a: u32, b: u32) -> Option { + let (carry, sum): (bool, u32) = jet::add_32(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +fn safe_add_32(a: u32, b: u32) -> u32 { + unwrap(checked_add_32(a, b)) +} + +fn checked_sub_32(a: u32, b: u32) -> Option { + let (borrow, diff): (bool, u32) = jet::subtract_32(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +fn safe_sub_32(a: u32, b: u32) -> u32 { + unwrap(checked_sub_32(a, b)) +} + +fn checked_mul_32(a: u32, b: u32) -> Option { + let result: u64 = jet::multiply_32(a, b); + + let (high, low): (u32, u32) = ::into(result); + + match jet::is_zero_32(high) { + true => Some(low), + false => None, + } +} + +fn safe_mul_32(a: u32, b: u32) -> u32 { + unwrap(checked_mul_32(a, b)) +} + +fn checked_div_32(a: u32, b: u32) -> Option { + match jet::is_zero_32(b) { + true => None, + false => Some(jet::divide_32(a, b)), + } +} + +fn safe_div_32(a: u32, b: u32) -> u32 { + unwrap(checked_div_32(a, b)) +} + +// helper +fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} + +fn main() { + let function_index: u8 = witness::FUNCTION_INDEX; + let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; + + let first_arg: u32 = witness::FIRST_ARG; + let second_arg: u32 = witness::SECOND_ARG; + let result: u32 = witness::RESULT; + + // add + match if_test_this_function(0, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: Option = checked_add_32(first_arg, second_arg); + assert!(is_none::(overflowing_u32)); + }, + false => { + let fitting_u32: Option = checked_add_32(first_arg, second_arg); + assert!(jet::eq_32(unwrap(fitting_u32), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(1, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: u32 = safe_add_32(first_arg, second_arg); + }, + false => { + let fitting_u32: u32 = safe_add_32(first_arg, second_arg); + assert!(jet::eq_32(fitting_u32, result)); + } + } + }, + false => (), + }; + + // subtract + match if_test_this_function(2, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: Option = checked_sub_32(first_arg, second_arg); + assert!(is_none::(overflowing_u32)); + }, + false => { + let fitting_u32: Option = checked_sub_32(first_arg, second_arg); + assert!(jet::eq_32(unwrap(fitting_u32), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(3, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: u32 = safe_sub_32(first_arg, second_arg); + }, + false => { + let fitting_u32: u32 = safe_sub_32(first_arg, second_arg); + assert!(jet::eq_32(fitting_u32, result)); + } + } + }, + false => (), + }; + + // multiply + match if_test_this_function(4, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: Option = checked_mul_32(first_arg, second_arg); + assert!(is_none::(overflowing_u32)); + }, + false => { + let fitting_u32: Option = checked_mul_32(first_arg, second_arg); + assert!(jet::eq_32(unwrap(fitting_u32), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(5, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: u32 = safe_mul_32(first_arg, second_arg); + }, + false => { + let fitting_u32: u32 = safe_mul_32(first_arg, second_arg); + assert!(jet::eq_32(fitting_u32, result)); + } + } + }, + false => (), + }; + + // divide + match if_test_this_function(6, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: Option = checked_div_32(first_arg, second_arg); + assert!(is_none::(overflowing_u32)); + }, + false => { + let fitting_u32: Option = checked_div_32(first_arg, second_arg); + assert!(jet::eq_32(unwrap(fitting_u32), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(7, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u32: u32 = safe_div_32(first_arg, second_arg); + }, + false => { + let fitting_u32: u32 = safe_div_32(first_arg, second_arg); + assert!(jet::eq_32(fitting_u32, result)); + } + } + }, + false => (), + }; +} diff --git a/simf/mock/u64_mock.simf b/simf/mock/u64_mock.simf new file mode 100644 index 0000000..55ae8e0 --- /dev/null +++ b/simf/mock/u64_mock.simf @@ -0,0 +1,194 @@ +// todo: switch to function import when available +fn checked_add_64(a: u64, b: u64) -> Option { + let (carry, sum): (bool, u64) = jet::add_64(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +fn safe_add_64(a: u64, b: u64) -> u64 { + unwrap(checked_add_64(a, b)) +} + +fn checked_sub_64(a: u64, b: u64) -> Option { + let (borrow, diff): (bool, u64) = jet::subtract_64(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +fn safe_sub_64(a: u64, b: u64) -> u64 { + unwrap(checked_sub_64(a, b)) +} + +fn checked_mul_64(a: u64, b: u64) -> Option { + let result: u128 = jet::multiply_64(a, b); + + let (high, low): (u64, u64) = ::into(result); + + match jet::is_zero_64(high) { + true => Some(low), + false => None, + } +} + +fn safe_mul_64(a: u64, b: u64) -> u64 { + unwrap(checked_mul_64(a, b)) +} + +fn checked_div_64(a: u64, b: u64) -> Option { + match jet::is_zero_64(b) { + true => None, + false => Some(jet::divide_64(a, b)), + } +} + +fn safe_div_64(a: u64, b: u64) -> u64 { + unwrap(checked_div_64(a, b)) +} + +// helper +fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} + +fn main() { + let function_index: u8 = witness::FUNCTION_INDEX; + let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; + + let first_arg: u64 = witness::FIRST_ARG; + let second_arg: u64 = witness::SECOND_ARG; + let result: u64 = witness::RESULT; + + // add + match if_test_this_function(0, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: Option = checked_add_64(first_arg, second_arg); + assert!(is_none::(overflowing_u64)); + }, + false => { + let fitting_u64: Option = checked_add_64(first_arg, second_arg); + assert!(jet::eq_64(unwrap(fitting_u64), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(1, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: u64 = safe_add_64(first_arg, second_arg); + }, + false => { + let fitting_u64: u64 = safe_add_64(first_arg, second_arg); + assert!(jet::eq_64(fitting_u64, result)); + } + } + }, + false => (), + }; + + // subtract + match if_test_this_function(2, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: Option = checked_sub_64(first_arg, second_arg); + assert!(is_none::(overflowing_u64)); + }, + false => { + let fitting_u64: Option = checked_sub_64(first_arg, second_arg); + assert!(jet::eq_64(unwrap(fitting_u64), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(3, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: u64 = safe_sub_64(first_arg, second_arg); + }, + false => { + let fitting_u64: u64 = safe_sub_64(first_arg, second_arg); + assert!(jet::eq_64(fitting_u64, result)); + } + } + }, + false => (), + }; + + // multiply + match if_test_this_function(4, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: Option = checked_mul_64(first_arg, second_arg); + assert!(is_none::(overflowing_u64)); + }, + false => { + let fitting_u64: Option = checked_mul_64(first_arg, second_arg); + assert!(jet::eq_64(unwrap(fitting_u64), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(5, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: u64 = safe_mul_64(first_arg, second_arg); + }, + false => { + let fitting_u64: u64 = safe_mul_64(first_arg, second_arg); + assert!(jet::eq_64(fitting_u64, result)); + } + } + }, + false => (), + }; + + // divide + match if_test_this_function(6, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: Option = checked_div_64(first_arg, second_arg); + assert!(is_none::(overflowing_u64)); + }, + false => { + let fitting_u64: Option = checked_div_64(first_arg, second_arg); + assert!(jet::eq_64(unwrap(fitting_u64), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(7, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u64: u64 = safe_div_64(first_arg, second_arg); + }, + false => { + let fitting_u64: u64 = safe_div_64(first_arg, second_arg); + assert!(jet::eq_64(fitting_u64, result)); + } + } + }, + false => (), + }; +} diff --git a/simf/mock/u8_mock.simf b/simf/mock/u8_mock.simf new file mode 100644 index 0000000..8f03ab1 --- /dev/null +++ b/simf/mock/u8_mock.simf @@ -0,0 +1,194 @@ +// todo: switch to function import when available +fn checked_add_8(a: u8, b: u8) -> Option { + let (carry, sum): (bool, u8) = jet::add_8(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +fn safe_add_8(a: u8, b: u8) -> u8 { + unwrap(checked_add_8(a, b)) +} + +fn checked_sub_8(a: u8, b: u8) -> Option { + let (borrow, diff): (bool, u8) = jet::subtract_8(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +fn safe_sub_8(a: u8, b: u8) -> u8 { + unwrap(checked_sub_8(a, b)) +} + +fn checked_mul_8(a: u8, b: u8) -> Option { + let result: u16 = jet::multiply_8(a, b); + + let (high, low): (u8, u8) = ::into(result); + + match jet::is_zero_8(high) { + true => Some(low), + false => None, + } +} + +fn safe_mul_8(a: u8, b: u8) -> u8 { + unwrap(checked_mul_8(a, b)) +} + +fn checked_div_8(a: u8, b: u8) -> Option { + match jet::is_zero_8(b) { + true => None, + false => Some(jet::divide_8(a, b)), + } +} + +fn safe_div_8(a: u8, b: u8) -> u8 { + unwrap(checked_div_8(a, b)) +} + +// helper +fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} + +fn main() { + let function_index: u8 = witness::FUNCTION_INDEX; + let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; + + let first_arg: u8 = witness::FIRST_ARG; + let second_arg: u8 = witness::SECOND_ARG; + let result: u8 = witness::RESULT; + + // add + match if_test_this_function(0, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: Option = checked_add_8(first_arg, second_arg); + assert!(is_none::(overflowing_u8)); + }, + false => { + let fitting_u8: Option = checked_add_8(first_arg, second_arg); + assert!(jet::eq_8(unwrap(fitting_u8), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(1, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: u8 = safe_add_8(first_arg, second_arg); + }, + false => { + let fitting_u8: u8 = safe_add_8(first_arg, second_arg); + assert!(jet::eq_8(fitting_u8, result)); + } + } + }, + false => (), + }; + + // subtract + match if_test_this_function(2, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: Option = checked_sub_8(first_arg, second_arg); + assert!(is_none::(overflowing_u8)); + }, + false => { + let fitting_u8: Option = checked_sub_8(first_arg, second_arg); + assert!(jet::eq_8(unwrap(fitting_u8), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(3, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: u8 = safe_sub_8(first_arg, second_arg); + }, + false => { + let fitting_u8: u8 = safe_sub_8(first_arg, second_arg); + assert!(jet::eq_8(fitting_u8, result)); + } + } + }, + false => (), + }; + + // multiply + match if_test_this_function(4, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: Option = checked_mul_8(first_arg, second_arg); + assert!(is_none::(overflowing_u8)); + }, + false => { + let fitting_u8: Option = checked_mul_8(first_arg, second_arg); + assert!(jet::eq_8(unwrap(fitting_u8), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(5, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: u8 = safe_mul_8(first_arg, second_arg); + }, + false => { + let fitting_u8: u8 = safe_mul_8(first_arg, second_arg); + assert!(jet::eq_8(fitting_u8, result)); + } + } + }, + false => (), + }; + + // divide + match if_test_this_function(6, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: Option = checked_div_8(first_arg, second_arg); + assert!(is_none::(overflowing_u8)); + }, + false => { + let fitting_u8: Option = checked_div_8(first_arg, second_arg); + assert!(jet::eq_8(unwrap(fitting_u8), result)); + } + } + }, + false => (), + }; + + match if_test_this_function(7, function_index) { + true => { + match if_test_overflow { + true => { + let overflowing_u8: u8 = safe_div_8(first_arg, second_arg); + }, + false => { + let fitting_u8: u8 = safe_div_8(first_arg, second_arg); + assert!(jet::eq_8(fitting_u8, result)); + } + } + }, + false => (), + }; +} diff --git a/simf/u16.simf b/simf/u16.simf new file mode 100644 index 0000000..f868482 --- /dev/null +++ b/simf/u16.simf @@ -0,0 +1,62 @@ +/// Returns the sum of two u16 values wrapped in Some, or None if the result overflows u16 +fn checked_add_16(a: u16, b: u16) -> Option { + let (carry, sum): (bool, u16) = jet::add_16(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +/// Returns the sum of two u16 values, panics if the result overflows u16 +fn safe_add_16(a: u16, b: u16) -> u16 { + unwrap(checked_add_16(a, b)) +} + +/// Returns the difference of two u16 values wrapped in Some, or None if the result overflows u16 +fn checked_sub_16(a: u16, b: u16) -> Option { + let (borrow, diff): (bool, u16) = jet::subtract_16(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +/// Returns the difference of two u16 values, panics if the result overflows u16 +fn safe_sub_16(a: u16, b: u16) -> u16 { + unwrap(checked_sub_16(a, b)) +} + +/// Returns the product of two u16 values wrapped in Some, or None if the result overflows u16 +fn checked_mul_16(a: u16, b: u16) -> Option { + let result: u32 = jet::multiply_16(a, b); + + let (high, low): (u16, u16) = ::into(result); + + match jet::is_zero_16(high) { + true => Some(low), + false => None, + } +} + +/// Returns the product of two u16 values, panics if the result overflows u16 +fn safe_mul_16(a: u16, b: u16) -> u16 { + unwrap(checked_mul_16(a, b)) +} + +/// Returns the quotient of two u16 values wrapped in Some, or None if the result overflows u16 +fn checked_div_16(a: u16, b: u16) -> Option { + match jet::is_zero_16(b) { + true => None, + false => Some(jet::divide_16(a, b)), + } +} + +/// Returns the quotient of two u16 values, panics if the result overflows u16 +fn safe_div_16(a: u16, b: u16) -> u16 { + unwrap(checked_div_16(a, b)) +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/simf/u32.simf b/simf/u32.simf new file mode 100644 index 0000000..500e9cb --- /dev/null +++ b/simf/u32.simf @@ -0,0 +1,62 @@ +/// Returns the sum of two u32 values wrapped in Some, or None if the result overflows u32 +fn checked_add_32(a: u32, b: u32) -> Option { + let (carry, sum): (bool, u32) = jet::add_32(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +/// Returns the sum of two u32 values, panics if the result overflows u32 +fn safe_add_32(a: u32, b: u32) -> u32 { + unwrap(checked_add_32(a, b)) +} + +/// Returns the sum of two u32 values, panics if the result overflows u32 +fn checked_sub_32(a: u32, b: u32) -> Option { + let (borrow, diff): (bool, u32) = jet::subtract_32(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +/// Returns the difference of two u32 values, panics if the result overflows u32 +fn safe_sub_32(a: u32, b: u32) -> u32 { + unwrap(checked_sub_32(a, b)) +} + +/// Returns the product of two u32 values wrapped in Some, or None if the result overflows u32 +fn checked_mul_32(a: u32, b: u32) -> Option { + let result: u64 = jet::multiply_32(a, b); + + let (high, low): (u32, u32) = ::into(result); + + match jet::is_zero_32(high) { + true => Some(low), + false => None, + } +} + +/// Returns the product of two u32 values, panics if the result overflows u32 +fn safe_mul_32(a: u32, b: u32) -> u32 { + unwrap(checked_mul_32(a, b)) +} + +/// Returns the quotient of two u32 values wrapped in Some, or None if the result overflows u32 +fn checked_div_32(a: u32, b: u32) -> Option { + match jet::is_zero_32(b) { + true => None, + false => Some(jet::divide_32(a, b)), + } +} + +/// Returns the quotient of two u32 values, panics if the result overflows u32 +fn safe_div_32(a: u32, b: u32) -> u32 { + unwrap(checked_div_32(a, b)) +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/simf/u64.simf b/simf/u64.simf new file mode 100644 index 0000000..e4bf114 --- /dev/null +++ b/simf/u64.simf @@ -0,0 +1,62 @@ +/// Returns the sum of two u64 values wrapped in Some, or None if the result overflows u64 +fn checked_add_64(a: u64, b: u64) -> Option { + let (carry, sum): (bool, u64) = jet::add_64(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +/// Returns the sum of two u64 values, panics if the result overflows u64 +fn safe_add_64(a: u64, b: u64) -> u64 { + unwrap(checked_add_64(a, b)) +} + +/// Returns the sum of two u64 values, panics if the result overflows u64 +fn checked_sub_64(a: u64, b: u64) -> Option { + let (borrow, diff): (bool, u64) = jet::subtract_64(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +/// Returns the difference of two u64 values, panics if the result overflows u64 +fn safe_sub_64(a: u64, b: u64) -> u64 { + unwrap(checked_sub_64(a, b)) +} + +/// Returns the product of two u64 values wrapped in Some, or None if the result overflows u64 +fn checked_mul_64(a: u64, b: u64) -> Option { + let result: u128 = jet::multiply_64(a, b); + + let (high, low): (u64, u64) = ::into(result); + + match jet::is_zero_64(high) { + true => Some(low), + false => None, + } +} + +/// Returns the product of two u64 values, panics if the result overflows u64 +fn safe_mul_64(a: u64, b: u64) -> u64 { + unwrap(checked_mul_64(a, b)) +} + +/// Returns the quotient of two u64 values wrapped in Some, or None if the result overflows u64 +fn checked_div_64(a: u64, b: u64) -> Option { + match jet::is_zero_64(b) { + true => None, + false => Some(jet::divide_64(a, b)), + } +} + +/// Returns the quotient of two u64 values, panics if the result overflows u64 +fn safe_div_64(a: u64, b: u64) -> u64 { + unwrap(checked_div_64(a, b)) +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/simf/u8.simf b/simf/u8.simf new file mode 100644 index 0000000..c5ea0ec --- /dev/null +++ b/simf/u8.simf @@ -0,0 +1,62 @@ +/// Returns the sum of two u8 values wrapped in Some, or None if the result overflows u8 +fn checked_add_8(a: u8, b: u8) -> Option { + let (carry, sum): (bool, u8) = jet::add_8(a, b); + + match carry { + true => None, + false => Some(sum), + } +} + +/// Returns the sum of two u8 values, panics if the result overflows u8 +fn safe_add_8(a: u8, b: u8) -> u8 { + unwrap(checked_add_8(a, b)) +} + +/// Returns the difference of two u8 values wrapped in Some, or None if the result overflows u8 +fn checked_sub_8(a: u8, b: u8) -> Option { + let (borrow, diff): (bool, u8) = jet::subtract_8(a, b); + + match borrow { + true => None, + false => Some(diff), + } +} + +/// Returns the difference of two u8 values, panics if the result overflows u8 +fn safe_sub_8(a: u8, b: u8) -> u8 { + unwrap(checked_sub_8(a, b)) +} + +/// Returns the product of two u8 values wrapped in Some, or None if the result overflows u8 +fn checked_mul_8(a: u8, b: u8) -> Option { + let result: u16 = jet::multiply_8(a, b); + + let (high, low): (u8, u8) = ::into(result); + + match jet::is_zero_8(high) { + true => Some(low), + false => None, + } +} + +/// Returns the product of two u8 values, panics if the result overflows u8 +fn safe_mul_8(a: u8, b: u8) -> u8 { + unwrap(checked_mul_8(a, b)) +} + +/// Returns the quotient of two u8 values wrapped in Some, or None if the result overflows u8 +fn checked_div_8(a: u8, b: u8) -> Option { + match jet::is_zero_8(b) { + true => None, + false => Some(jet::divide_8(a, b)), + } +} + +/// Returns the quotient of two u8 values, panics if the result overflows u8 +fn safe_div_8(a: u8, b: u8) -> u8 { + unwrap(checked_div_8(a, b)) +} + +// todo: remove after module functionality is implemented +fn main() {} diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index b593cee..5b15146 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -8,6 +8,7 @@ use simplicityhl_std::artifacts::mock::asserts_mock::derived_asserts_mock::{ }; mod helper; + use crate::helper::{cast_to_bool, generate_uints_in_one_range}; enum FunctionToTest { diff --git a/tests/u16_test.rs b/tests/u16_test.rs new file mode 100644 index 0000000..ecf5942 --- /dev/null +++ b/tests/u16_test.rs @@ -0,0 +1,426 @@ +use rand::Rng; + +use simplex::simplicityhl::elements::Script; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::u16_mock::U16MockProgram; +use simplicityhl_std::artifacts::mock::u16_mock::derived_u16_mock::{ + U16MockArguments, U16MockWitness, +}; + +mod helper; + +use crate::helper::{IfTestOverflow, cast_to_bool}; + +enum FunctionToTest { + CheckedAdd16, + SafeAdd16, + CheckedSub16, + SafeSub16, + CheckedMul16, + SafeMul16, + CheckedDiv16, + SafeDiv16, +} + +fn get_script(context: &simplex::TestContext) -> (U16MockProgram, Script) { + let arguments = U16MockArguments {}; + + let u16_program = U16MockProgram::new(arguments); + + let u16_script = u16_program.get_script_pubkey(context.get_network()); + + (u16_program, u16_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, u16_script) = get_script(context); + + let tx_receipt = signer.send(u16_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script( + context: &simplex::TestContext, + function_index: FunctionToTest, + if_test_overflow: IfTestOverflow, + first_arg: u16, + second_arg: u16, + result: u16, +) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (u16_program, u16_script) = get_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&u16_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = U16MockWitness { + function_index: function_index as u8, + if_test_overflow: cast_to_bool(if_test_overflow as u8), + first_arg, + second_arg, + result, + }; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new( + Box::new(u16_program.as_ref().clone()), + Box::new(witness.clone()), + ), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_add_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u16::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_add_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u16::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u16::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_add_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u16::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeAdd16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_add_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u16::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u16::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeAdd16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_sub_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_sub_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u16::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_sub_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeSub16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_sub_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u16::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeSub16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_mul_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u16.pow(16 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u16.pow(16 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_mul_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u16::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u16::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_mul_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u16.pow(16 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u16.pow(16 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeMul16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_mul_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u16::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u16::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeMul16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_div_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u16::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_checked_div_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_div_16_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u16::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeDiv16, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u16_test_safe_div_16_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u16::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeDiv16, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} diff --git a/tests/u32_test.rs b/tests/u32_test.rs new file mode 100644 index 0000000..53f8810 --- /dev/null +++ b/tests/u32_test.rs @@ -0,0 +1,426 @@ +use rand::Rng; + +use simplex::simplicityhl::elements::Script; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::u32_mock::U32MockProgram; +use simplicityhl_std::artifacts::mock::u32_mock::derived_u32_mock::{ + U32MockArguments, U32MockWitness, +}; + +mod helper; + +use crate::helper::{IfTestOverflow, cast_to_bool}; + +enum FunctionToTest { + CheckedAdd32, + SafeAdd32, + CheckedSub32, + SafeSub32, + CheckedMul32, + SafeMul32, + CheckedDiv32, + SafeDiv32, +} + +fn get_script(context: &simplex::TestContext) -> (U32MockProgram, Script) { + let arguments = U32MockArguments {}; + + let u32_program = U32MockProgram::new(arguments); + + let u32_script = u32_program.get_script_pubkey(context.get_network()); + + (u32_program, u32_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, u32_script) = get_script(context); + + let tx_receipt = signer.send(u32_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script( + context: &simplex::TestContext, + function_index: FunctionToTest, + if_test_overflow: IfTestOverflow, + first_arg: u32, + second_arg: u32, + result: u32, +) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (u32_program, u32_script) = get_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&u32_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = U32MockWitness { + function_index: function_index as u8, + if_test_overflow: cast_to_bool(if_test_overflow as u8), + first_arg, + second_arg, + result, + }; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new( + Box::new(u32_program.as_ref().clone()), + Box::new(witness.clone()), + ), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_add_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u32::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_add_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u32::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u32::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_add_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u32::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeAdd32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_add_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u32::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u32::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeAdd32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_sub_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_sub_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u32::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_sub_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeSub32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_sub_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u32::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeSub32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_mul_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u32.pow(32 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u32.pow(32 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_mul_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u32::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u32::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_mul_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u32.pow(32 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u32.pow(32 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeMul32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_mul_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u32::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u32::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeMul32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_div_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u32::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_checked_div_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_div_32_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u32::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeDiv32, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u32_test_safe_div_32_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u32::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeDiv32, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} diff --git a/tests/u64_test.rs b/tests/u64_test.rs new file mode 100644 index 0000000..39f00d7 --- /dev/null +++ b/tests/u64_test.rs @@ -0,0 +1,426 @@ +use rand::Rng; + +use simplex::simplicityhl::elements::Script; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::u64_mock::U64MockProgram; +use simplicityhl_std::artifacts::mock::u64_mock::derived_u64_mock::{ + U64MockArguments, U64MockWitness, +}; + +mod helper; + +use crate::helper::{IfTestOverflow, cast_to_bool}; + +enum FunctionToTest { + CheckedAdd64, + SafeAdd64, + CheckedSub64, + SafeSub64, + CheckedMul64, + SafeMul64, + CheckedDiv64, + SafeDiv64, +} + +fn get_script(context: &simplex::TestContext) -> (U64MockProgram, Script) { + let arguments = U64MockArguments {}; + + let u64_program = U64MockProgram::new(arguments); + + let u64_script = u64_program.get_script_pubkey(context.get_network()); + + (u64_program, u64_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, u64_script) = get_script(context); + + let tx_receipt = signer.send(u64_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script( + context: &simplex::TestContext, + function_index: FunctionToTest, + if_test_overflow: IfTestOverflow, + first_arg: u64, + second_arg: u64, + result: u64, +) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (u64_program, u64_script) = get_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&u64_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = U64MockWitness { + function_index: function_index as u8, + if_test_overflow: cast_to_bool(if_test_overflow as u8), + first_arg, + second_arg, + result, + }; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new( + Box::new(u64_program.as_ref().clone()), + Box::new(witness.clone()), + ), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_add_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u64::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_add_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u64::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u64::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_add_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u64::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeAdd64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_add_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u64::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u64::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeAdd64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_sub_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_sub_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u64::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_sub_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeSub64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_sub_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u64::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeSub64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_mul_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u64.pow(64 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u64.pow(64 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_mul_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u64::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u64::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_mul_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u64.pow(64 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u64.pow(64 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeMul64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_mul_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u64::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u64::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeMul64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_div_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u64::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_checked_div_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_div_64_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u64::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeDiv64, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u64_test_safe_div_64_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u64::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeDiv64, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} diff --git a/tests/u8_test.rs b/tests/u8_test.rs new file mode 100644 index 0000000..e8e5ccf --- /dev/null +++ b/tests/u8_test.rs @@ -0,0 +1,424 @@ +use rand::Rng; + +use simplex::simplicityhl::elements::Script; + +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +use simplicityhl_std::artifacts::mock::u8_mock::U8MockProgram; +use simplicityhl_std::artifacts::mock::u8_mock::derived_u8_mock::{U8MockArguments, U8MockWitness}; + +mod helper; + +use crate::helper::{IfTestOverflow, cast_to_bool}; + +enum FunctionToTest { + CheckedAdd8, + SafeAdd8, + CheckedSub8, + SafeSub8, + CheckedMul8, + SafeMul8, + CheckedDiv8, + SafeDiv8, +} + +fn get_script(context: &simplex::TestContext) -> (U8MockProgram, Script) { + let arguments = U8MockArguments {}; + + let u8_program = U8MockProgram::new(arguments); + + let u8_script = u8_program.get_script_pubkey(context.get_network()); + + (u8_program, u8_script) +} + +fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + + let (_, u8_script) = get_script(context); + + let tx_receipt = signer.send(u8_script.clone(), 50)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +fn spend_script( + context: &simplex::TestContext, + function_index: FunctionToTest, + if_test_overflow: IfTestOverflow, + first_arg: u8, + second_arg: u8, + result: u8, +) -> anyhow::Result<()> { + let signer = context.get_default_signer(); + let provider = context.get_default_provider(); + + let (u8_program, u8_script) = get_script(context); + + let asserts_utxos = provider.fetch_scripthash_utxos(&u8_script)?; + + let mut ft = FinalTransaction::new(); + + let witness = U8MockWitness { + function_index: function_index as u8, + if_test_overflow: cast_to_bool(if_test_overflow as u8), + first_arg, + second_arg, + result, + }; + + ft.add_program_input( + PartialInput::new(asserts_utxos[0].clone()), + ProgramInput::new( + Box::new(u8_program.as_ref().clone()), + Box::new(witness.clone()), + ), + RequiredSignature::None, + ); + + let tx_receipt = signer.broadcast(&ft)?; + println!("Broadcast: {}", tx_receipt); + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_add_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u8::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_add_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u8::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u8::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedAdd8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_add_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX / 2); + let second_arg = rand::thread_rng().gen_range(0..=u8::MAX / 2); + let result = first_arg + second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeAdd8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_add_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u8::MAX; + let second_arg = rand::thread_rng().gen_range(1..=u8::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeAdd8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_sub_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_sub_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u8::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedSub8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_sub_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = rand::thread_rng().gen_range(0..=first_arg); + let result = first_arg - second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeSub8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_sub_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX - 1); + let second_arg = rand::thread_rng().gen_range(first_arg + 1..=u8::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeSub8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_mul_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u8.pow(8 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u8.pow(8 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_mul_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u8::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u8::MAX); + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedMul8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_mul_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..2_u8.pow(8 / 2)); + let second_arg = rand::thread_rng().gen_range(0..2_u8.pow(8 / 2)); + let result = first_arg * second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeMul8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_mul_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = u8::MAX; + let second_arg = rand::thread_rng().gen_range(2..=u8::MAX); + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeMul8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_div_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u8::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_checked_div_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::CheckedDiv8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_div_8_not_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = rand::thread_rng().gen_range(1..=u8::MAX); + let result = first_arg / second_arg; + + fund_script(&context)?; + spend_script( + &context, + FunctionToTest::SafeDiv8, + IfTestOverflow::NotOverflow, + first_arg, + second_arg, + result, + )?; + + Ok(()) +} + +#[simplex::test] +fn u8_test_safe_div_8_overflow(context: simplex::TestContext) -> anyhow::Result<()> { + let first_arg = rand::thread_rng().gen_range(0..=u8::MAX); + let second_arg = 0; + let result = 0; + + fund_script(&context)?; + + let txid_result = spend_script( + &context, + FunctionToTest::SafeDiv8, + IfTestOverflow::Overflow, + first_arg, + second_arg, + result, + ); + + assert!( + txid_result.is_err(), + "Expected this test to fail but it succeeded" + ); + + let err: String = txid_result.unwrap_err().to_string(); + assert!(err.contains("Failed to prune program: Execution reached a pruned branch")); + + Ok(()) +} From 7bb72e2a7427daa61e21752dd779dc460ca4aa9c Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Tue, 23 Jun 2026 18:30:30 +0300 Subject: [PATCH 07/13] Updated readme (#15) * updated readme * added instructions for smplx installation --- README.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/README.md b/README.md index f29ea14..8e198c8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,74 @@ # SimplicityHL Standard Library This repository contains the standard library for [SimplicityHL](https://github.com/BlockstreamResearch/SimplicityHL). + +## Dev Info +### Installation + +> Project currently uses Simplex version 0.0.6. + +To compile the project, execute the following command: + +```bash +cargo build +``` + +To download simplexup, run: + +```bash +curl -L https://smplx.simplicity-lang.org | bash +``` + +To install a specific Simplex version (in this case the v0.0.6 version): + +```bash +simplexup --install v0.0.6 +``` + +### Compilation + +To compile the contracts, execute the following command: + +```bash +simplex build +``` + +To clean up generated artifacts: + +```bash +simplex clean +``` + +### Test + +To run the tests with logs (`-v` or `-vv` is available), execute the following command: + +```bash +simplex test -v +``` + +To run the tests using multiple threads: + +```bash +simplex test --test-threads 8 +``` + +To run a specific test: + +```bash +simplex test test_name +``` + +### Linting + +To format the rust files, execute the following command: + +```bash +cargo fmt +``` + +To check the project for common mistakes: + +```bash +cargo clippy --workspace --all-targets --all-features -- -D warnings +``` From 64741abb00940f7bb7a288277fb9b26e1ecd9ded Mon Sep 17 00:00:00 2001 From: Yuliia Aritkulova <94910987+aritkulova@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:34:37 +0300 Subject: [PATCH 08/13] Feat/modules (#17) * updated contracts to use modules and imports * updated u8, u16, u32 and u64 contracts to use modules and imports * fixing ci by using smplx from specific commit * trying to fix ci * updated readme --- .github/workflows/tests.yml | 2 + Cargo.lock | 469 ++++++++----------- Cargo.toml | 3 +- README.md | 9 +- simf/{mock => }/asserts_mock.simf | 52 +- simf/helper.simf | 3 + simf/{ => lib}/asserts.simf | 25 +- simf/{ => lib}/logical_operations.simf | 9 +- simf/{ => lib}/u16.simf | 19 +- simf/{ => lib}/u32.simf | 19 +- simf/{ => lib}/u64.simf | 19 +- simf/{ => lib}/u8.simf | 19 +- simf/{mock => }/logical_operations_mock.simf | 13 +- simf/{mock => }/u16_mock.simf | 58 +-- simf/{mock => }/u32_mock.simf | 58 +-- simf/{mock => }/u64_mock.simf | 58 +-- simf/{mock => }/u8_mock.simf | 58 +-- tests/asserts_test.rs | 4 +- tests/logical_operations_test.rs | 4 +- tests/u16_test.rs | 6 +- tests/u32_test.rs | 6 +- tests/u64_test.rs | 6 +- tests/u8_test.rs | 4 +- 23 files changed, 283 insertions(+), 640 deletions(-) rename simf/{mock => }/asserts_mock.simf (72%) create mode 100644 simf/helper.simf rename simf/{ => lib}/asserts.simf (65%) rename simf/{ => lib}/logical_operations.simf (69%) rename simf/{ => lib}/u16.simf (76%) rename simf/{ => lib}/u32.simf (76%) rename simf/{ => lib}/u64.simf (76%) rename simf/{ => lib}/u8.simf (77%) rename simf/{mock => }/logical_operations_mock.simf (50%) rename simf/{mock => }/u16_mock.simf (78%) rename simf/{mock => }/u32_mock.simf (78%) rename simf/{mock => }/u64_mock.simf (78%) rename simf/{mock => }/u8_mock.simf (78%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2178d4a..f1d8ca2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,6 +46,8 @@ jobs: - name: Install simplex-cli uses: ./.github/actions/setup-smplx + with: + commit-sha: '3afcc04aae8a0a92722b28bc1d16ef27983d4aa1' - name: Generate contract artifacts shell: bash diff --git a/Cargo.lock b/Cargo.lock index c59c2ed..328caf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" [[package]] name = "autocfg" @@ -94,11 +94,33 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "base58ck" -version = "0.1.100" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5dc7e09f7bb15f0062da7c03086d6b71a2c84e0af4fccbbc7d8c6559847816" +checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0" dependencies = [ "bitcoin_hashes", ] @@ -136,9 +158,9 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.32.100" +version = "0.32.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39581299241111285f3268ba75ddf372746fd041620918b145c1af9d75e91b6c" +checksum = "8ed8ccb78a9ff7a6fbb90e2fb9b8588b4a9928d49d8af3cb789108a84ea6b0ce" dependencies = [ "base58ck", "base64 0.21.7", @@ -146,17 +168,38 @@ dependencies = [ "bitcoin-io", "bitcoin-units", "bitcoin_hashes", - "hex-conservative", + "hex-conservative 0.2.2", "hex_lit", "secp256k1", "serde", ] +[[package]] +name = "bitcoin-consensus-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40" +dependencies = [ + "bitcoin-internals", +] + +[[package]] +name = "bitcoin-internals" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64" +dependencies = [ + "hex-conservative 0.3.2", +] + [[package]] name = "bitcoin-io" -version = "0.1.100" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11301df0b06f22dea7bb1916403fdd88a371031e495c49b8f96931b28189e175" +checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78" +dependencies = [ + "bitcoin-consensus-encoding", +] [[package]] name = "bitcoin-private" @@ -166,21 +209,22 @@ checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" [[package]] name = "bitcoin-units" -version = "0.1.100" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bad157b78d0d1b22c4cbb6a35a566211fc4d14866a37f2c780652b50f3b845" +checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51" dependencies = [ + "bitcoin-consensus-encoding", "serde", ] [[package]] name = "bitcoin_hashes" -version = "0.14.100" +version = "0.14.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9901a56e133a1fc86eeb1113e2591f45f4682451ca893bff494d2f88918e3f" +checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative", + "hex-conservative 0.2.2", "serde", ] @@ -266,11 +310,13 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.63" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -321,6 +367,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -382,6 +437,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -424,9 +485,9 @@ dependencies = [ [[package]] name = "elements" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b2569d3495bfdfce36c504fd4d78752ff4a7699f8a33e6f3ee523bddf9f6ad" +checksum = "83c63a04238f4b7f3564fe9705921452c2900efd00982545e5c634fac9024fe2" dependencies = [ "bech32", "bitcoin", @@ -481,6 +542,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-core" version = "0.3.32" @@ -530,15 +597,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", - "wasip3", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", ] [[package]] @@ -594,12 +671,6 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hex" version = "0.4.3" @@ -615,6 +686,15 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hex-conservative" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex_lit" version = "0.1.1" @@ -639,12 +719,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ignore" version = "0.4.26" @@ -669,8 +743,6 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", - "serde", - "serde_core", ] [[package]] @@ -694,11 +766,21 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" -version = "0.3.100" +version = "0.3.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" +checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" dependencies = [ "cfg-if", "futures-util", @@ -712,17 +794,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3662a38d341d77efecb73caf01420cfa5aa63c0253fd7bc05289ef9f6616e1bf" dependencies = [ "base64 0.13.1", - "minreq", + "minreq 2.14.1", "serde", "serde_json", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" version = "0.2.186" @@ -743,15 +819,15 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "log" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memoffset" @@ -777,6 +853,16 @@ name = "minreq" version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "minreq" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659579df697b372ef9e36f02fcbb41f6d6f157dcec7db9c9618fa0f23cf0fc20" dependencies = [ "rustls", "rustls-webpki", @@ -878,13 +964,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" @@ -921,18 +1013,6 @@ dependencies = [ "getrandom 0.2.17", ] -[[package]] -name = "regex" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.14", - "regex-syntax 0.8.11", -] - [[package]] name = "regex-automata" version = "0.3.9" @@ -1009,23 +1089,37 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ + "aws-lc-rs", "log", - "ring", + "once_cell", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ + "aws-lc-rs", "ring", + "rustls-pki-types", "untrusted", ] @@ -1044,25 +1138,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "santiago" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de36022292bc2086eb8f55bffa460fef3475e4459b478820711f4c421feb87ec" -dependencies = [ - "regex", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "secp256k1" version = "0.29.1" @@ -1107,12 +1182,6 @@ dependencies = [ "secp256k1-sys", ] -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - [[package]] name = "serde" version = "1.0.228" @@ -1184,9 +1253,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simplicity-lang" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e57bd4d84853974a212eab24ed89da54f49fbccf5e33e93bcd29f0a6591cd5" +checksum = "13ed081e3046d66c146d7201bcbf3b655ca3436cb83f6efc26d7895bd2b79d06" dependencies = [ "bitcoin", "bitcoin_hashes", @@ -1194,17 +1263,16 @@ dependencies = [ "elements", "getrandom 0.2.17", "ghost-cell", - "hex-conservative", + "hex-conservative 0.2.2", "miniscript", - "santiago", "simplicity-sys", ] [[package]] name = "simplicity-sys" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3401ee7331f183a5458c0f5a4b3d5d00bde0fd12e2e03728c537df34efae289" +checksum = "96d1ec5477c7650b8ef511aa56dccb28f2e8cdb6e87f260ecffdaf0ebfef2d3b" dependencies = [ "bitcoin_hashes", "cc", @@ -1212,9 +1280,8 @@ dependencies = [ [[package]] name = "simplicityhl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25de8990174fe3e1a843df138cacc4265d05839ebd2550c18b9196f567d55e81" +version = "0.6.0-rc.0" +source = "git+https://github.com/BlockstreamResearch/SimplicityHL.git#4eb97f5dcb28d294f23bee15cb8f2e85027cd1f6" dependencies = [ "base64 0.21.7", "chumsky", @@ -1246,8 +1313,7 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smplx-build" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb75724fd0329de24895b58a4010efeeca9773092294845a324aee141ec3c864" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "glob", "globwalk", @@ -1265,8 +1331,7 @@ dependencies = [ [[package]] name = "smplx-macros" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4777f6ff9a27faf98396181d67f04f720e0c472c2a3f1db76c5475b45da8963f" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "smplx-build", "smplx-test", @@ -1276,8 +1341,7 @@ dependencies = [ [[package]] name = "smplx-regtest" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3711284f8ad7859ae0605841e90316bdf41be5b09011639e765667f07feb5d" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "electrsd", "hex", @@ -1292,8 +1356,7 @@ dependencies = [ [[package]] name = "smplx-sdk" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96c7de4f86f4a74dc4c910d6d0541d63cd661e3f616566054a36e589ffcda2c" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "bip39", "bitcoin_hashes", @@ -1301,7 +1364,7 @@ dependencies = [ "electrsd", "elements-miniscript", "hex", - "minreq", + "minreq 3.0.0", "serde", "serde_json", "sha2", @@ -1312,8 +1375,7 @@ dependencies = [ [[package]] name = "smplx-std" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cef91f2523cfb6e8937bb1c8004869d539e0dcd8c62fef68c93cc3a6233117" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "either", "serde", @@ -1326,8 +1388,7 @@ dependencies = [ [[package]] name = "smplx-test" version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9c8878fae6868b9fbf7ed7cb3e261dc308b55ea418bb4421685dad99f98fc1f" +source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" dependencies = [ "electrsd", "proc-macro2", @@ -1368,9 +1429,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -1384,7 +1445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", @@ -1491,12 +1552,6 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "untrusted" version = "0.9.0" @@ -1533,27 +1588,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.123" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" +checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" dependencies = [ "cfg-if", "once_cell", @@ -1564,9 +1610,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.123" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" +checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1574,9 +1620,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.123" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" +checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" dependencies = [ "bumpalo", "proc-macro2", @@ -1587,53 +1633,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.123" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" +checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" dependencies = [ "unicode-ident", ] [[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" +name = "webpki-roots" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" dependencies = [ - "bitflags 2.13.0", - "hashbrown 0.15.5", - "indexmap", - "semver", + "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "which" version = "4.4.2" @@ -1764,100 +1779,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.13.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "zerocopy" version = "0.8.52" @@ -1878,6 +1805,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index c2cd2be..23aeac9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ rust-version = "1.91.0" version = "0.1.0" [dependencies] -smplx-std = { version = ">=0.0.6, <0.1.0" } +# todo: Replace git dependency with crates.io version that supports modules once available +smplx-std = { git = "https://github.com/BlockstreamResearch/smplx.git", rev = "3afcc04" } anyhow = { version = "1.0.101" } rand = { version = "0.8.6" } diff --git a/README.md b/README.md index 8e198c8..c6ef5c7 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,13 @@ This repository contains the standard library for [SimplicityHL](https://github.com/BlockstreamResearch/SimplicityHL). +> [!NOTE] +> If you are using the VS Code syntax highlighting extension, you may see errors because the extension does not support modules and imports yet. + ## Dev Info ### Installation -> Project currently uses Simplex version 0.0.6. +> Project currently uses Simplex version 0.0.6 from the dev branch. To compile the project, execute the following command: @@ -19,10 +22,10 @@ To download simplexup, run: curl -L https://smplx.simplicity-lang.org | bash ``` -To install a specific Simplex version (in this case the v0.0.6 version): +To install a specific Simplex version (in this case from the specific commit): ```bash -simplexup --install v0.0.6 +simplexup --commit 3afcc04aae8a0a92722b28bc1d16ef27983d4aa1 ``` ### Compilation diff --git a/simf/mock/asserts_mock.simf b/simf/asserts_mock.simf similarity index 72% rename from simf/mock/asserts_mock.simf rename to simf/asserts_mock.simf index fe2fb62..32daeb6 100644 --- a/simf/mock/asserts_mock.simf +++ b/simf/asserts_mock.simf @@ -1,54 +1,6 @@ -// todo: switch to function import when available -fn assert_eq_8(a: u8, b: u8) { // 0 - assert!(jet::eq_8(a, b)); -} - -fn assert_eq_16(a: u16, b: u16) { // 1 - assert!(jet::eq_16(a, b)); -} - -fn assert_eq_32(a: u32, b: u32) { // 2 - assert!(jet::eq_32(a, b)); -} - -fn assert_eq_64(a: u64, b: u64) { // 3 - assert!(jet::eq_64(a, b)); -} - -// todo: assert_eq_128 - -fn assert_eq_256(a: u256, b: u256) { // 4 - assert!(jet::eq_256(a, b)); -} - -fn assert_none_8(val: Option) { // 5 - assert!(is_none::(val)); -} +use crate::lib::asserts::{assert_eq_8, assert_eq_16, assert_eq_32, assert_eq_64, assert_eq_256, assert_none_8, assert_none_16, assert_none_32, assert_none_64,assert_none_128, assert_none_256}; -fn assert_none_16(val: Option) { // 6 - assert!(is_none::(val)); -} - -fn assert_none_32(val: Option) { // 7 - assert!(is_none::(val)); -} - -fn assert_none_64(val: Option) { // 8 - assert!(is_none::(val)); -} - -fn assert_none_128(val: Option) { // 9 - assert!(is_none::(val)); -} - -fn assert_none_256(val: Option) { // 10 - assert!(is_none::(val)); -} - -// helper -fn if_test_this_function(index: u8, flag: u8) -> bool { - jet::eq_8(index, flag) -} +use crate::helper::if_test_this_function; fn main() { let function_index: u8 = witness::FUNCTION_INDEX; diff --git a/simf/helper.simf b/simf/helper.simf new file mode 100644 index 0000000..60ae726 --- /dev/null +++ b/simf/helper.simf @@ -0,0 +1,3 @@ +pub fn if_test_this_function(index: u8, flag: u8) -> bool { + jet::eq_8(index, flag) +} diff --git a/simf/asserts.simf b/simf/lib/asserts.simf similarity index 65% rename from simf/asserts.simf rename to simf/lib/asserts.simf index 7707a59..e5121d4 100644 --- a/simf/asserts.simf +++ b/simf/lib/asserts.simf @@ -1,59 +1,56 @@ /// Asserts that two u8 are equal -fn assert_eq_8(a: u8, b: u8) { +pub fn assert_eq_8(a: u8, b: u8) { assert!(jet::eq_8(a, b)); } /// Asserts that two u16 are equal -fn assert_eq_16(a: u16, b: u16) { +pub fn assert_eq_16(a: u16, b: u16) { assert!(jet::eq_16(a, b)); } /// Asserts that two u32 are equal -fn assert_eq_32(a: u32, b: u32) { +pub fn assert_eq_32(a: u32, b: u32) { assert!(jet::eq_32(a, b)); } /// Asserts that two u64 are equal -fn assert_eq_64(a: u64, b: u64) { +pub fn assert_eq_64(a: u64, b: u64) { assert!(jet::eq_64(a, b)); } // todo: assert_eq_128 /// Asserts that two u256 are equal -fn assert_eq_256(a: u256, b: u256) { +pub fn assert_eq_256(a: u256, b: u256) { assert!(jet::eq_256(a, b)); } /// Asserts that provided u8 Option value is a None -fn assert_none_8(val: Option) { +pub fn assert_none_8(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u16 Option value is a None -fn assert_none_16(val: Option) { +pub fn assert_none_16(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u32 Option value is a None -fn assert_none_32(val: Option) { +pub fn assert_none_32(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u64 Option value is a None -fn assert_none_64(val: Option) { +pub fn assert_none_64(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u128 Option value is a None -fn assert_none_128(val: Option) { +pub fn assert_none_128(val: Option) { assert!(is_none::(val)); } /// Asserts that provided u256 Option value is a None -fn assert_none_256(val: Option) { +pub fn assert_none_256(val: Option) { assert!(is_none::(val)); } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/logical_operations.simf b/simf/lib/logical_operations.simf similarity index 69% rename from simf/logical_operations.simf rename to simf/lib/logical_operations.simf index a8b94de..63ea8e6 100644 --- a/simf/logical_operations.simf +++ b/simf/lib/logical_operations.simf @@ -1,17 +1,14 @@ /// Returns the result of the NOT operation on the provided value -fn not(bit: bool) -> bool { +pub fn not(bit: bool) -> bool { ::into(jet::complement_1(::into(bit))) } /// Returns the result of the OR operation on the provided values -fn or(a: bool, b: bool) -> bool { +pub fn or(a: bool, b: bool) -> bool { ::into(jet::or_1(::into(a), ::into(b))) } /// Returns the result of the AND operation on the provided values -fn and(a: bool, b: bool) -> bool { +pub fn and(a: bool, b: bool) -> bool { ::into(jet::and_1(::into(a), ::into(b))) } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/u16.simf b/simf/lib/u16.simf similarity index 76% rename from simf/u16.simf rename to simf/lib/u16.simf index f868482..4b1da2a 100644 --- a/simf/u16.simf +++ b/simf/lib/u16.simf @@ -1,5 +1,5 @@ /// Returns the sum of two u16 values wrapped in Some, or None if the result overflows u16 -fn checked_add_16(a: u16, b: u16) -> Option { +pub fn checked_add_16(a: u16, b: u16) -> Option { let (carry, sum): (bool, u16) = jet::add_16(a, b); match carry { @@ -9,12 +9,12 @@ fn checked_add_16(a: u16, b: u16) -> Option { } /// Returns the sum of two u16 values, panics if the result overflows u16 -fn safe_add_16(a: u16, b: u16) -> u16 { +pub fn safe_add_16(a: u16, b: u16) -> u16 { unwrap(checked_add_16(a, b)) } /// Returns the difference of two u16 values wrapped in Some, or None if the result overflows u16 -fn checked_sub_16(a: u16, b: u16) -> Option { +pub fn checked_sub_16(a: u16, b: u16) -> Option { let (borrow, diff): (bool, u16) = jet::subtract_16(a, b); match borrow { @@ -24,12 +24,12 @@ fn checked_sub_16(a: u16, b: u16) -> Option { } /// Returns the difference of two u16 values, panics if the result overflows u16 -fn safe_sub_16(a: u16, b: u16) -> u16 { +pub fn safe_sub_16(a: u16, b: u16) -> u16 { unwrap(checked_sub_16(a, b)) } /// Returns the product of two u16 values wrapped in Some, or None if the result overflows u16 -fn checked_mul_16(a: u16, b: u16) -> Option { +pub fn checked_mul_16(a: u16, b: u16) -> Option { let result: u32 = jet::multiply_16(a, b); let (high, low): (u16, u16) = ::into(result); @@ -41,12 +41,12 @@ fn checked_mul_16(a: u16, b: u16) -> Option { } /// Returns the product of two u16 values, panics if the result overflows u16 -fn safe_mul_16(a: u16, b: u16) -> u16 { +pub fn safe_mul_16(a: u16, b: u16) -> u16 { unwrap(checked_mul_16(a, b)) } /// Returns the quotient of two u16 values wrapped in Some, or None if the result overflows u16 -fn checked_div_16(a: u16, b: u16) -> Option { +pub fn checked_div_16(a: u16, b: u16) -> Option { match jet::is_zero_16(b) { true => None, false => Some(jet::divide_16(a, b)), @@ -54,9 +54,6 @@ fn checked_div_16(a: u16, b: u16) -> Option { } /// Returns the quotient of two u16 values, panics if the result overflows u16 -fn safe_div_16(a: u16, b: u16) -> u16 { +pub fn safe_div_16(a: u16, b: u16) -> u16 { unwrap(checked_div_16(a, b)) } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/u32.simf b/simf/lib/u32.simf similarity index 76% rename from simf/u32.simf rename to simf/lib/u32.simf index 500e9cb..909fc56 100644 --- a/simf/u32.simf +++ b/simf/lib/u32.simf @@ -1,5 +1,5 @@ /// Returns the sum of two u32 values wrapped in Some, or None if the result overflows u32 -fn checked_add_32(a: u32, b: u32) -> Option { +pub fn checked_add_32(a: u32, b: u32) -> Option { let (carry, sum): (bool, u32) = jet::add_32(a, b); match carry { @@ -9,12 +9,12 @@ fn checked_add_32(a: u32, b: u32) -> Option { } /// Returns the sum of two u32 values, panics if the result overflows u32 -fn safe_add_32(a: u32, b: u32) -> u32 { +pub fn safe_add_32(a: u32, b: u32) -> u32 { unwrap(checked_add_32(a, b)) } /// Returns the sum of two u32 values, panics if the result overflows u32 -fn checked_sub_32(a: u32, b: u32) -> Option { +pub fn checked_sub_32(a: u32, b: u32) -> Option { let (borrow, diff): (bool, u32) = jet::subtract_32(a, b); match borrow { @@ -24,12 +24,12 @@ fn checked_sub_32(a: u32, b: u32) -> Option { } /// Returns the difference of two u32 values, panics if the result overflows u32 -fn safe_sub_32(a: u32, b: u32) -> u32 { +pub fn safe_sub_32(a: u32, b: u32) -> u32 { unwrap(checked_sub_32(a, b)) } /// Returns the product of two u32 values wrapped in Some, or None if the result overflows u32 -fn checked_mul_32(a: u32, b: u32) -> Option { +pub fn checked_mul_32(a: u32, b: u32) -> Option { let result: u64 = jet::multiply_32(a, b); let (high, low): (u32, u32) = ::into(result); @@ -41,12 +41,12 @@ fn checked_mul_32(a: u32, b: u32) -> Option { } /// Returns the product of two u32 values, panics if the result overflows u32 -fn safe_mul_32(a: u32, b: u32) -> u32 { +pub fn safe_mul_32(a: u32, b: u32) -> u32 { unwrap(checked_mul_32(a, b)) } /// Returns the quotient of two u32 values wrapped in Some, or None if the result overflows u32 -fn checked_div_32(a: u32, b: u32) -> Option { +pub fn checked_div_32(a: u32, b: u32) -> Option { match jet::is_zero_32(b) { true => None, false => Some(jet::divide_32(a, b)), @@ -54,9 +54,6 @@ fn checked_div_32(a: u32, b: u32) -> Option { } /// Returns the quotient of two u32 values, panics if the result overflows u32 -fn safe_div_32(a: u32, b: u32) -> u32 { +pub fn safe_div_32(a: u32, b: u32) -> u32 { unwrap(checked_div_32(a, b)) } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/u64.simf b/simf/lib/u64.simf similarity index 76% rename from simf/u64.simf rename to simf/lib/u64.simf index e4bf114..913dbdc 100644 --- a/simf/u64.simf +++ b/simf/lib/u64.simf @@ -1,5 +1,5 @@ /// Returns the sum of two u64 values wrapped in Some, or None if the result overflows u64 -fn checked_add_64(a: u64, b: u64) -> Option { +pub fn checked_add_64(a: u64, b: u64) -> Option { let (carry, sum): (bool, u64) = jet::add_64(a, b); match carry { @@ -9,12 +9,12 @@ fn checked_add_64(a: u64, b: u64) -> Option { } /// Returns the sum of two u64 values, panics if the result overflows u64 -fn safe_add_64(a: u64, b: u64) -> u64 { +pub fn safe_add_64(a: u64, b: u64) -> u64 { unwrap(checked_add_64(a, b)) } /// Returns the sum of two u64 values, panics if the result overflows u64 -fn checked_sub_64(a: u64, b: u64) -> Option { +pub fn checked_sub_64(a: u64, b: u64) -> Option { let (borrow, diff): (bool, u64) = jet::subtract_64(a, b); match borrow { @@ -24,12 +24,12 @@ fn checked_sub_64(a: u64, b: u64) -> Option { } /// Returns the difference of two u64 values, panics if the result overflows u64 -fn safe_sub_64(a: u64, b: u64) -> u64 { +pub fn safe_sub_64(a: u64, b: u64) -> u64 { unwrap(checked_sub_64(a, b)) } /// Returns the product of two u64 values wrapped in Some, or None if the result overflows u64 -fn checked_mul_64(a: u64, b: u64) -> Option { +pub fn checked_mul_64(a: u64, b: u64) -> Option { let result: u128 = jet::multiply_64(a, b); let (high, low): (u64, u64) = ::into(result); @@ -41,12 +41,12 @@ fn checked_mul_64(a: u64, b: u64) -> Option { } /// Returns the product of two u64 values, panics if the result overflows u64 -fn safe_mul_64(a: u64, b: u64) -> u64 { +pub fn safe_mul_64(a: u64, b: u64) -> u64 { unwrap(checked_mul_64(a, b)) } /// Returns the quotient of two u64 values wrapped in Some, or None if the result overflows u64 -fn checked_div_64(a: u64, b: u64) -> Option { +pub fn checked_div_64(a: u64, b: u64) -> Option { match jet::is_zero_64(b) { true => None, false => Some(jet::divide_64(a, b)), @@ -54,9 +54,6 @@ fn checked_div_64(a: u64, b: u64) -> Option { } /// Returns the quotient of two u64 values, panics if the result overflows u64 -fn safe_div_64(a: u64, b: u64) -> u64 { +pub fn safe_div_64(a: u64, b: u64) -> u64 { unwrap(checked_div_64(a, b)) } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/u8.simf b/simf/lib/u8.simf similarity index 77% rename from simf/u8.simf rename to simf/lib/u8.simf index c5ea0ec..d3b87f7 100644 --- a/simf/u8.simf +++ b/simf/lib/u8.simf @@ -1,5 +1,5 @@ /// Returns the sum of two u8 values wrapped in Some, or None if the result overflows u8 -fn checked_add_8(a: u8, b: u8) -> Option { +pub fn checked_add_8(a: u8, b: u8) -> Option { let (carry, sum): (bool, u8) = jet::add_8(a, b); match carry { @@ -9,12 +9,12 @@ fn checked_add_8(a: u8, b: u8) -> Option { } /// Returns the sum of two u8 values, panics if the result overflows u8 -fn safe_add_8(a: u8, b: u8) -> u8 { +pub fn safe_add_8(a: u8, b: u8) -> u8 { unwrap(checked_add_8(a, b)) } /// Returns the difference of two u8 values wrapped in Some, or None if the result overflows u8 -fn checked_sub_8(a: u8, b: u8) -> Option { +pub fn checked_sub_8(a: u8, b: u8) -> Option { let (borrow, diff): (bool, u8) = jet::subtract_8(a, b); match borrow { @@ -24,12 +24,12 @@ fn checked_sub_8(a: u8, b: u8) -> Option { } /// Returns the difference of two u8 values, panics if the result overflows u8 -fn safe_sub_8(a: u8, b: u8) -> u8 { +pub fn safe_sub_8(a: u8, b: u8) -> u8 { unwrap(checked_sub_8(a, b)) } /// Returns the product of two u8 values wrapped in Some, or None if the result overflows u8 -fn checked_mul_8(a: u8, b: u8) -> Option { +pub fn checked_mul_8(a: u8, b: u8) -> Option { let result: u16 = jet::multiply_8(a, b); let (high, low): (u8, u8) = ::into(result); @@ -41,12 +41,12 @@ fn checked_mul_8(a: u8, b: u8) -> Option { } /// Returns the product of two u8 values, panics if the result overflows u8 -fn safe_mul_8(a: u8, b: u8) -> u8 { +pub fn safe_mul_8(a: u8, b: u8) -> u8 { unwrap(checked_mul_8(a, b)) } /// Returns the quotient of two u8 values wrapped in Some, or None if the result overflows u8 -fn checked_div_8(a: u8, b: u8) -> Option { +pub fn checked_div_8(a: u8, b: u8) -> Option { match jet::is_zero_8(b) { true => None, false => Some(jet::divide_8(a, b)), @@ -54,9 +54,6 @@ fn checked_div_8(a: u8, b: u8) -> Option { } /// Returns the quotient of two u8 values, panics if the result overflows u8 -fn safe_div_8(a: u8, b: u8) -> u8 { +pub fn safe_div_8(a: u8, b: u8) -> u8 { unwrap(checked_div_8(a, b)) } - -// todo: remove after module functionality is implemented -fn main() {} diff --git a/simf/mock/logical_operations_mock.simf b/simf/logical_operations_mock.simf similarity index 50% rename from simf/mock/logical_operations_mock.simf rename to simf/logical_operations_mock.simf index 4ab4e22..e428ec6 100644 --- a/simf/mock/logical_operations_mock.simf +++ b/simf/logical_operations_mock.simf @@ -1,15 +1,4 @@ -// todo: switch to function import when available -fn not(bit: bool) -> bool { - ::into(jet::complement_1(::into(bit))) -} - -fn or(a: bool, b: bool) -> bool { - ::into(jet::or_1(::into(a), ::into(b))) -} - -fn and(a: bool, b: bool) -> bool { - ::into(jet::and_1(::into(a), ::into(b))) -} +use crate::lib::logical_operations::{not, or, and}; fn main() { assert!(not(false)); diff --git a/simf/mock/u16_mock.simf b/simf/u16_mock.simf similarity index 78% rename from simf/mock/u16_mock.simf rename to simf/u16_mock.simf index ff893d4..ffe58c0 100644 --- a/simf/mock/u16_mock.simf +++ b/simf/u16_mock.simf @@ -1,60 +1,6 @@ -// todo: switch to function import when available -fn checked_add_16(a: u16, b: u16) -> Option { - let (carry, sum): (bool, u16) = jet::add_16(a, b); +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}; - match carry { - true => None, - false => Some(sum), - } -} - -fn safe_add_16(a: u16, b: u16) -> u16 { - unwrap(checked_add_16(a, b)) -} - -fn checked_sub_16(a: u16, b: u16) -> Option { - let (borrow, diff): (bool, u16) = jet::subtract_16(a, b); - - match borrow { - true => None, - false => Some(diff), - } -} - -fn safe_sub_16(a: u16, b: u16) -> u16 { - unwrap(checked_sub_16(a, b)) -} - -fn checked_mul_16(a: u16, b: u16) -> Option { - let result: u32 = jet::multiply_16(a, b); - - let (high, low): (u16, u16) = ::into(result); - - match jet::is_zero_16(high) { - true => Some(low), - false => None, - } -} - -fn safe_mul_16(a: u16, b: u16) -> u16 { - unwrap(checked_mul_16(a, b)) -} - -fn checked_div_16(a: u16, b: u16) -> Option { - match jet::is_zero_16(b) { - true => None, - false => Some(jet::divide_16(a, b)), - } -} - -fn safe_div_16(a: u16, b: u16) -> u16 { - unwrap(checked_div_16(a, b)) -} - -// helper -fn if_test_this_function(index: u8, flag: u8) -> bool { - jet::eq_8(index, flag) -} +use crate::helper::if_test_this_function; fn main() { let function_index: u8 = witness::FUNCTION_INDEX; diff --git a/simf/mock/u32_mock.simf b/simf/u32_mock.simf similarity index 78% rename from simf/mock/u32_mock.simf rename to simf/u32_mock.simf index 2c14b28..a1ae4b4 100644 --- a/simf/mock/u32_mock.simf +++ b/simf/u32_mock.simf @@ -1,60 +1,6 @@ -// todo: switch to function import when available -fn checked_add_32(a: u32, b: u32) -> Option { - let (carry, sum): (bool, u32) = jet::add_32(a, b); +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}; - match carry { - true => None, - false => Some(sum), - } -} - -fn safe_add_32(a: u32, b: u32) -> u32 { - unwrap(checked_add_32(a, b)) -} - -fn checked_sub_32(a: u32, b: u32) -> Option { - let (borrow, diff): (bool, u32) = jet::subtract_32(a, b); - - match borrow { - true => None, - false => Some(diff), - } -} - -fn safe_sub_32(a: u32, b: u32) -> u32 { - unwrap(checked_sub_32(a, b)) -} - -fn checked_mul_32(a: u32, b: u32) -> Option { - let result: u64 = jet::multiply_32(a, b); - - let (high, low): (u32, u32) = ::into(result); - - match jet::is_zero_32(high) { - true => Some(low), - false => None, - } -} - -fn safe_mul_32(a: u32, b: u32) -> u32 { - unwrap(checked_mul_32(a, b)) -} - -fn checked_div_32(a: u32, b: u32) -> Option { - match jet::is_zero_32(b) { - true => None, - false => Some(jet::divide_32(a, b)), - } -} - -fn safe_div_32(a: u32, b: u32) -> u32 { - unwrap(checked_div_32(a, b)) -} - -// helper -fn if_test_this_function(index: u8, flag: u8) -> bool { - jet::eq_8(index, flag) -} +use crate::helper::if_test_this_function; fn main() { let function_index: u8 = witness::FUNCTION_INDEX; diff --git a/simf/mock/u64_mock.simf b/simf/u64_mock.simf similarity index 78% rename from simf/mock/u64_mock.simf rename to simf/u64_mock.simf index 55ae8e0..5f20922 100644 --- a/simf/mock/u64_mock.simf +++ b/simf/u64_mock.simf @@ -1,60 +1,6 @@ -// todo: switch to function import when available -fn checked_add_64(a: u64, b: u64) -> Option { - let (carry, sum): (bool, u64) = jet::add_64(a, b); +use crate::lib::u64::{checked_add_64, safe_add_64, checked_sub_64, safe_sub_64, checked_mul_64, safe_mul_64, checked_div_64, safe_div_64}; - match carry { - true => None, - false => Some(sum), - } -} - -fn safe_add_64(a: u64, b: u64) -> u64 { - unwrap(checked_add_64(a, b)) -} - -fn checked_sub_64(a: u64, b: u64) -> Option { - let (borrow, diff): (bool, u64) = jet::subtract_64(a, b); - - match borrow { - true => None, - false => Some(diff), - } -} - -fn safe_sub_64(a: u64, b: u64) -> u64 { - unwrap(checked_sub_64(a, b)) -} - -fn checked_mul_64(a: u64, b: u64) -> Option { - let result: u128 = jet::multiply_64(a, b); - - let (high, low): (u64, u64) = ::into(result); - - match jet::is_zero_64(high) { - true => Some(low), - false => None, - } -} - -fn safe_mul_64(a: u64, b: u64) -> u64 { - unwrap(checked_mul_64(a, b)) -} - -fn checked_div_64(a: u64, b: u64) -> Option { - match jet::is_zero_64(b) { - true => None, - false => Some(jet::divide_64(a, b)), - } -} - -fn safe_div_64(a: u64, b: u64) -> u64 { - unwrap(checked_div_64(a, b)) -} - -// helper -fn if_test_this_function(index: u8, flag: u8) -> bool { - jet::eq_8(index, flag) -} +use crate::helper::if_test_this_function; fn main() { let function_index: u8 = witness::FUNCTION_INDEX; diff --git a/simf/mock/u8_mock.simf b/simf/u8_mock.simf similarity index 78% rename from simf/mock/u8_mock.simf rename to simf/u8_mock.simf index 8f03ab1..d45fcd3 100644 --- a/simf/mock/u8_mock.simf +++ b/simf/u8_mock.simf @@ -1,60 +1,6 @@ -// todo: switch to function import when available -fn checked_add_8(a: u8, b: u8) -> Option { - let (carry, sum): (bool, u8) = jet::add_8(a, b); +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}; - match carry { - true => None, - false => Some(sum), - } -} - -fn safe_add_8(a: u8, b: u8) -> u8 { - unwrap(checked_add_8(a, b)) -} - -fn checked_sub_8(a: u8, b: u8) -> Option { - let (borrow, diff): (bool, u8) = jet::subtract_8(a, b); - - match borrow { - true => None, - false => Some(diff), - } -} - -fn safe_sub_8(a: u8, b: u8) -> u8 { - unwrap(checked_sub_8(a, b)) -} - -fn checked_mul_8(a: u8, b: u8) -> Option { - let result: u16 = jet::multiply_8(a, b); - - let (high, low): (u8, u8) = ::into(result); - - match jet::is_zero_8(high) { - true => Some(low), - false => None, - } -} - -fn safe_mul_8(a: u8, b: u8) -> u8 { - unwrap(checked_mul_8(a, b)) -} - -fn checked_div_8(a: u8, b: u8) -> Option { - match jet::is_zero_8(b) { - true => None, - false => Some(jet::divide_8(a, b)), - } -} - -fn safe_div_8(a: u8, b: u8) -> u8 { - unwrap(checked_div_8(a, b)) -} - -// helper -fn if_test_this_function(index: u8, flag: u8) -> bool { - jet::eq_8(index, flag) -} +use crate::helper::if_test_this_function; fn main() { let function_index: u8 = witness::FUNCTION_INDEX; diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index 5b15146..a13a988 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -2,8 +2,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::asserts_mock::AssertsMockProgram; -use simplicityhl_std::artifacts::mock::asserts_mock::derived_asserts_mock::{ +use simplicityhl_std::artifacts::asserts_mock::AssertsMockProgram; +use simplicityhl_std::artifacts::asserts_mock::derived_asserts_mock::{ AssertsMockArguments, AssertsMockWitness, }; diff --git a/tests/logical_operations_test.rs b/tests/logical_operations_test.rs index 035211d..55fb092 100644 --- a/tests/logical_operations_test.rs +++ b/tests/logical_operations_test.rs @@ -2,8 +2,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::logical_operations_mock::LogicalOperationsMockProgram; -use simplicityhl_std::artifacts::mock::logical_operations_mock::derived_logical_operations_mock::{ +use simplicityhl_std::artifacts::logical_operations_mock::LogicalOperationsMockProgram; +use simplicityhl_std::artifacts::logical_operations_mock::derived_logical_operations_mock::{ LogicalOperationsMockArguments, LogicalOperationsMockWitness, }; diff --git a/tests/u16_test.rs b/tests/u16_test.rs index ecf5942..70fd686 100644 --- a/tests/u16_test.rs +++ b/tests/u16_test.rs @@ -4,10 +4,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::u16_mock::U16MockProgram; -use simplicityhl_std::artifacts::mock::u16_mock::derived_u16_mock::{ - U16MockArguments, U16MockWitness, -}; +use simplicityhl_std::artifacts::u16_mock::U16MockProgram; +use simplicityhl_std::artifacts::u16_mock::derived_u16_mock::{U16MockArguments, U16MockWitness}; mod helper; diff --git a/tests/u32_test.rs b/tests/u32_test.rs index 53f8810..43b4718 100644 --- a/tests/u32_test.rs +++ b/tests/u32_test.rs @@ -4,10 +4,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::u32_mock::U32MockProgram; -use simplicityhl_std::artifacts::mock::u32_mock::derived_u32_mock::{ - U32MockArguments, U32MockWitness, -}; +use simplicityhl_std::artifacts::u32_mock::U32MockProgram; +use simplicityhl_std::artifacts::u32_mock::derived_u32_mock::{U32MockArguments, U32MockWitness}; mod helper; diff --git a/tests/u64_test.rs b/tests/u64_test.rs index 39f00d7..2372073 100644 --- a/tests/u64_test.rs +++ b/tests/u64_test.rs @@ -4,10 +4,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::u64_mock::U64MockProgram; -use simplicityhl_std::artifacts::mock::u64_mock::derived_u64_mock::{ - U64MockArguments, U64MockWitness, -}; +use simplicityhl_std::artifacts::u64_mock::U64MockProgram; +use simplicityhl_std::artifacts::u64_mock::derived_u64_mock::{U64MockArguments, U64MockWitness}; mod helper; diff --git a/tests/u8_test.rs b/tests/u8_test.rs index e8e5ccf..4ce3178 100644 --- a/tests/u8_test.rs +++ b/tests/u8_test.rs @@ -4,8 +4,8 @@ use simplex::simplicityhl::elements::Script; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplicityhl_std::artifacts::mock::u8_mock::U8MockProgram; -use simplicityhl_std::artifacts::mock::u8_mock::derived_u8_mock::{U8MockArguments, U8MockWitness}; +use simplicityhl_std::artifacts::u8_mock::U8MockProgram; +use simplicityhl_std::artifacts::u8_mock::derived_u8_mock::{U8MockArguments, U8MockWitness}; mod helper; From 7d30e26fb39b76f80ecff62c738b9bd219b2ac52 Mon Sep 17 00:00:00 2001 From: Yevhenii Sekhin Date: Wed, 1 Jul 2026 17:23:39 +0300 Subject: [PATCH 09/13] Refactor library architecture (#19) * feat: recode `uint` operations for clarity * feat: refactor `asserts_test.rs` and `README.md` a bit * refactor: docstring a little bit more * update: version of Simplex to `0.0.7` * refactor: docstring for macros and simf code a bit --- .github/actions/setup-smplx/action.yml | 2 +- .github/workflows/tests.yml | 2 - Cargo.lock | 86 +- Cargo.toml | 3 +- README.md | 37 +- Simplex.toml | 6 +- simf/asserts_mock.simf | 102 --- simf/asserts_test.simf | 39 + ...ations_mock.simf => logical_ops_test.simf} | 2 +- simf/u16_mock.simf | 140 ---- simf/u16_test.simf | 37 + simf/u32_mock.simf | 140 ---- simf/u32_test.simf | 37 + simf/u64_mock.simf | 140 ---- simf/u64_test.simf | 37 + simf/u8_mock.simf | 140 ---- simf/u8_test.simf | 37 + tests/asserts_test.rs | 755 +++++++----------- tests/common/core.rs | 94 +++ tests/common/mod.rs | 2 + tests/common/uint.rs | 291 +++++++ tests/helper.rs | 32 - tests/logical_operations_test.rs | 65 -- tests/logical_ops_test.rs | 18 + tests/u16_test.rs | 442 +--------- tests/u32_test.rs | 442 +--------- tests/u64_test.rs | 442 +--------- tests/u8_test.rs | 442 +--------- 28 files changed, 1058 insertions(+), 2954 deletions(-) delete mode 100644 simf/asserts_mock.simf create mode 100644 simf/asserts_test.simf rename simf/{logical_operations_mock.simf => logical_ops_test.simf} (92%) delete mode 100644 simf/u16_mock.simf create mode 100644 simf/u16_test.simf delete mode 100644 simf/u32_mock.simf create mode 100644 simf/u32_test.simf delete mode 100644 simf/u64_mock.simf create mode 100644 simf/u64_test.simf delete mode 100644 simf/u8_mock.simf create mode 100644 simf/u8_test.simf create mode 100644 tests/common/core.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/common/uint.rs delete mode 100644 tests/helper.rs delete mode 100644 tests/logical_operations_test.rs create mode 100644 tests/logical_ops_test.rs diff --git a/.github/actions/setup-smplx/action.yml b/.github/actions/setup-smplx/action.yml index e118fdf..5b2eff4 100644 --- a/.github/actions/setup-smplx/action.yml +++ b/.github/actions/setup-smplx/action.yml @@ -17,6 +17,6 @@ runs: shell: bash run: | set -euo pipefail - REVISION="${{ inputs.commit-sha}}" + REVISION="${{ inputs.commit-sha }}" OWNER_REPO="${{ inputs.owner-repo }}" bash "$GITHUB_WORKSPACE/.github/scripts/setup-smplx" "${REVISION}" "${OWNER_REPO}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f1d8ca2..2178d4a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,8 +46,6 @@ jobs: - name: Install simplex-cli uses: ./.github/actions/setup-smplx - with: - commit-sha: '3afcc04aae8a0a92722b28bc1d16ef27983d4aa1' - name: Generate contract artifacts shell: bash diff --git a/Cargo.lock b/Cargo.lock index 328caf1..d345b91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "ar_archive_writer" @@ -96,9 +96,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "zeroize", @@ -106,14 +106,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] @@ -288,12 +289,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", - "serde", + "serde_core", ] [[package]] @@ -778,9 +779,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.102" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", @@ -924,6 +925,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1104,9 +1111,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "zeroize", ] @@ -1280,8 +1287,9 @@ dependencies = [ [[package]] name = "simplicityhl" -version = "0.6.0-rc.0" -source = "git+https://github.com/BlockstreamResearch/SimplicityHL.git#4eb97f5dcb28d294f23bee15cb8f2e85027cd1f6" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361316795ec753230c421d964ab60940d20d5252c2d39272452528832c9e0ec5" dependencies = [ "base64 0.21.7", "chumsky", @@ -1312,8 +1320,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smplx-build" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f090cc306bc000e1f926d0fbbf92080626530095a3b4541caf8f6b8bedb0a62" dependencies = [ "glob", "globwalk", @@ -1330,8 +1339,9 @@ dependencies = [ [[package]] name = "smplx-macros" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6758957dde925b558d5453fbf39ca551ee3e0ae04b032686aa5444e695455595" dependencies = [ "smplx-build", "smplx-test", @@ -1340,8 +1350,9 @@ dependencies = [ [[package]] name = "smplx-regtest" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e96c8226c35603c08f37dda2fa319f4d822790c2f0d922d690a952399a4c92" dependencies = [ "electrsd", "hex", @@ -1355,13 +1366,14 @@ dependencies = [ [[package]] name = "smplx-sdk" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68d02d154ff3b7459f86e60dd60edd693a7f60b91ba1ccb29c34be171796fce6" dependencies = [ "bip39", "bitcoin_hashes", + "bitcoincore-rpc", "dyn-clone", - "electrsd", "elements-miniscript", "hex", "minreq 3.0.0", @@ -1374,8 +1386,9 @@ dependencies = [ [[package]] name = "smplx-std" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d7cde217178eddb3f50572d2d728560388cc74899e38ca9aee0378f3d261db" dependencies = [ "either", "serde", @@ -1387,8 +1400,9 @@ dependencies = [ [[package]] name = "smplx-test" -version = "0.0.6" -source = "git+https://github.com/BlockstreamResearch/smplx.git?rev=3afcc04#3afcc04aae8a0a92722b28bc1d16ef27983d4aa1" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200a3f0cf072ffb8df5f841e478d7c46d5649d6d2f0487b5c72a0731d7c882a1" dependencies = [ "electrsd", "proc-macro2", @@ -1597,9 +1611,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -1610,9 +1624,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1620,9 +1634,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -1633,9 +1647,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index 23aeac9..01718c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,7 @@ rust-version = "1.91.0" version = "0.1.0" [dependencies] -# todo: Replace git dependency with crates.io version that supports modules once available -smplx-std = { git = "https://github.com/BlockstreamResearch/smplx.git", rev = "3afcc04" } +smplx-std = "0.0.7" anyhow = { version = "1.0.101" } rand = { version = "0.8.6" } diff --git a/README.md b/README.md index c6ef5c7..209b95b 100644 --- a/README.md +++ b/README.md @@ -3,32 +3,22 @@ This repository contains the standard library for [SimplicityHL](https://github.com/BlockstreamResearch/SimplicityHL). > [!NOTE] -> If you are using the VS Code syntax highlighting extension, you may see errors because the extension does not support modules and imports yet. +> The VS Code syntax-highlighting extension does not yet support modules and imports, so you may see spurious errors when editing files in this repo. -## Dev Info -### Installation +## Installation -> Project currently uses Simplex version 0.0.6 from the dev branch. +> Project currently uses Simplex version `0.0.7`. -To compile the project, execute the following command: - -```bash -cargo build -``` - -To download simplexup, run: +Install `siplexup`, then use it to install the pinned Simplex toolchain: ```bash curl -L https://smplx.simplicity-lang.org | bash +simplexup ``` -To install a specific Simplex version (in this case from the specific commit): - -```bash -simplexup --commit 3afcc04aae8a0a92722b28bc1d16ef27983d4aa1 -``` +## Usage -### Compilation +### Build To compile the contracts, execute the following command: @@ -56,22 +46,21 @@ To run the tests using multiple threads: simplex test --test-threads 8 ``` -To run a specific test: +To run a specific test module: ```bash -simplex test test_name +simplex test u8_test ``` -### Linting - -To format the rust files, execute the following command: +To run a specific test: ```bash -cargo fmt +simplex test test_name ``` -To check the project for common mistakes: +### Lint & format ```bash +cargo fmt cargo clippy --workspace --all-targets --all-features -- -D warnings ``` diff --git a/Simplex.toml b/Simplex.toml index 1c78892..c522f64 100644 --- a/Simplex.toml +++ b/Simplex.toml @@ -1,10 +1,13 @@ -# Default Simplex Config +# DEFAULT CONFIG # [build] # src_dir = "./simf" # simf_files = ["*.simf"] # out_dir = "./src/artifacts" +# [dependencies] +# some_dep = { git = "", path = "" } + # [regtest] # mnemonic = "exist carry drive collect lend cereal occur much tiger just involve mean" # bitcoins = 10_000_000 @@ -16,6 +19,7 @@ # [test] # mnemonic = "exist carry drive collect lend cereal occur much tiger just involve mean" # bitcoins = 10_000_000 +# verbosity = 0 # [test.esplora] # url = "" diff --git a/simf/asserts_mock.simf b/simf/asserts_mock.simf deleted file mode 100644 index 32daeb6..0000000 --- a/simf/asserts_mock.simf +++ /dev/null @@ -1,102 +0,0 @@ -use crate::lib::asserts::{assert_eq_8, assert_eq_16, assert_eq_32, assert_eq_64, assert_eq_256, assert_none_8, assert_none_16, assert_none_32, assert_none_64,assert_none_128, assert_none_256}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - - let first_arg_u8: Option = witness::FIRST_ARG_U8; - let second_arg_u8: Option = witness::SECOND_ARG_U8; - - let first_arg_u16: Option = witness::FIRST_ARG_U16; - let second_arg_u16: Option = witness::SECOND_ARG_U16; - - let first_arg_u32: Option = witness::FIRST_ARG_U32; - let second_arg_u32: Option = witness::SECOND_ARG_U32; - - let first_arg_u64: Option = witness::FIRST_ARG_U64; - let second_arg_u64: Option = witness::SECOND_ARG_U64; - - let first_arg_u128: Option = witness::FIRST_ARG_U128; - let second_arg_u128: Option = witness::SECOND_ARG_U128; - - let first_arg_u256: Option = witness::FIRST_ARG_U256; - let second_arg_u256: Option = witness::SECOND_ARG_U256; - - match if_test_this_function(0, function_index) { - true => { - assert_eq_8(unwrap(first_arg_u8), unwrap(second_arg_u8)); - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - assert_eq_16(unwrap(first_arg_u16), unwrap(second_arg_u16)); - }, - false => (), - }; - - match if_test_this_function(2, function_index) { - true => { - assert_eq_32(unwrap(first_arg_u32), unwrap(second_arg_u32)); - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - assert_eq_64(unwrap(first_arg_u64), unwrap(second_arg_u64)); - }, - false => (), - }; - - match if_test_this_function(4, function_index) { - true => { - assert_eq_256(unwrap(first_arg_u256), unwrap(second_arg_u256)); - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - assert_none_8(first_arg_u8); - }, - false => (), - }; - - match if_test_this_function(6, function_index) { - true => { - assert_none_16(first_arg_u16); - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - assert_none_32(first_arg_u32); - }, - false => (), - }; - - match if_test_this_function(8, function_index) { - true => { - assert_none_64(first_arg_u64); - }, - false => (), - }; - - match if_test_this_function(9, function_index) { - true => { - assert_none_128(first_arg_u128); - }, - false => (), - }; - - match if_test_this_function(10, function_index) { - true => { - assert_none_256(first_arg_u256); - }, - false => (), - }; -} diff --git a/simf/asserts_test.simf b/simf/asserts_test.simf new file mode 100644 index 0000000..c09675e --- /dev/null +++ b/simf/asserts_test.simf @@ -0,0 +1,39 @@ +use crate::lib::asserts::{assert_eq_8, assert_eq_16, assert_eq_32, assert_eq_64, assert_eq_256, assert_none_8, assert_none_16, assert_none_32, assert_none_64,assert_none_128, assert_none_256}; +use crate::helper::if_test_this_function; + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a_u8: Option = witness::FIRST_ARG_U8; + let b_u8: Option = witness::SECOND_ARG_U8; + + let a_u16: Option = witness::FIRST_ARG_U16; + let b_u16: Option = witness::SECOND_ARG_U16; + + let a_u32: Option = witness::FIRST_ARG_U32; + let b_u32: Option = witness::SECOND_ARG_U32; + + let a_u64: Option = witness::FIRST_ARG_U64; + let b_u64: Option = witness::SECOND_ARG_U64; + + let a_u128: Option = witness::FIRST_ARG_U128; + let b_u128: Option = witness::SECOND_ARG_U128; + + let a_u256: Option = witness::FIRST_ARG_U256; + let b_u256: Option = witness::SECOND_ARG_U256; + + // Assert Eq + match if_test_this_function(0, fn_idx) { true => { assert_eq_8(unwrap(a_u8), unwrap(b_u8)); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert_eq_16(unwrap(a_u16), unwrap(b_u16)); }, false => (), }; + match if_test_this_function(2, fn_idx) { true => { assert_eq_32(unwrap(a_u32), unwrap(b_u32)); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert_eq_64(unwrap(a_u64), unwrap(b_u64)); }, false => (), }; + match if_test_this_function(4, fn_idx) { true => { assert_eq_256(unwrap(a_u256), unwrap(b_u256)); }, false => (), }; + + // Assert None + match if_test_this_function(5, fn_idx) { true => { assert_none_8(a_u8); }, false => (), }; + match if_test_this_function(6, fn_idx) { true => { assert_none_16(a_u16); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert_none_32(a_u32); }, false => (), }; + match if_test_this_function(8, fn_idx) { true => { assert_none_64(a_u64); }, false => (), }; + match if_test_this_function(9, fn_idx) { true => { assert_none_128(a_u128); }, false => (), }; + match if_test_this_function(10, fn_idx) { true => { assert_none_256(a_u256); }, false => (), }; +} diff --git a/simf/logical_operations_mock.simf b/simf/logical_ops_test.simf similarity index 92% rename from simf/logical_operations_mock.simf rename to simf/logical_ops_test.simf index e428ec6..45e48e4 100644 --- a/simf/logical_operations_mock.simf +++ b/simf/logical_ops_test.simf @@ -2,7 +2,7 @@ use crate::lib::logical_operations::{not, or, and}; fn main() { assert!(not(false)); - assert!(not((not(true)))); + assert!(not(not(true))); assert!(or(true, false)); assert!(or(false, true)); diff --git a/simf/u16_mock.simf b/simf/u16_mock.simf deleted file mode 100644 index ffe58c0..0000000 --- a/simf/u16_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -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}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u16 = witness::FIRST_ARG; - let second_arg: u16 = witness::SECOND_ARG; - let result: u16 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_add_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_add_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_add_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_add_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_sub_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_sub_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_sub_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_sub_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_mul_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_mul_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_mul_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_mul_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_div_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_div_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_div_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_div_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u16_test.simf b/simf/u16_test.simf new file mode 100644 index 0000000..3a57f73 --- /dev/null +++ b/simf/u16_test.simf @@ -0,0 +1,37 @@ +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}; +use crate::lib::asserts::{assert_none_16, assert_eq_16}; +use crate::helper::if_test_this_function; + +/// Asserts a `checked_*` result equals the expected Option. +/// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +/// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert_none_16(result), + Some(e: u16) => assert_eq_16(unwrap(result), e), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u16 = witness::FIRST_ARG; + let b: u16 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_16(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_16(safe_add_16(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_16(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_16(safe_sub_16(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_16(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_16(safe_mul_16(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_16(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_16(safe_div_16(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/simf/u32_mock.simf b/simf/u32_mock.simf deleted file mode 100644 index a1ae4b4..0000000 --- a/simf/u32_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -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}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u32 = witness::FIRST_ARG; - let second_arg: u32 = witness::SECOND_ARG; - let result: u32 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_add_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_add_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_add_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_add_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_sub_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_sub_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_sub_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_sub_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_mul_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_mul_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_mul_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_mul_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_div_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_div_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_div_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_div_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u32_test.simf b/simf/u32_test.simf new file mode 100644 index 0000000..6222ee8 --- /dev/null +++ b/simf/u32_test.simf @@ -0,0 +1,37 @@ +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}; +use crate::lib::asserts::{assert_none_32, assert_eq_32}; +use crate::helper::if_test_this_function; + +/// Asserts a `checked_*` result equals the expected Option. +/// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +/// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert_none_32(result), + Some(e: u32) => assert_eq_32(unwrap(result), e), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u32 = witness::FIRST_ARG; + let b: u32 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_32(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_32(safe_add_32(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_32(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_32(safe_sub_32(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_32(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_32(safe_mul_32(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_32(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_32(safe_div_32(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/simf/u64_mock.simf b/simf/u64_mock.simf deleted file mode 100644 index 5f20922..0000000 --- a/simf/u64_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -use crate::lib::u64::{checked_add_64, safe_add_64, checked_sub_64, safe_sub_64, checked_mul_64, safe_mul_64, checked_div_64, safe_div_64}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u64 = witness::FIRST_ARG; - let second_arg: u64 = witness::SECOND_ARG; - let result: u64 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_add_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_add_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_add_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_add_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_sub_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_sub_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_sub_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_sub_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_mul_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_mul_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_mul_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_mul_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_div_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_div_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_div_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_div_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u64_test.simf b/simf/u64_test.simf new file mode 100644 index 0000000..955d2c3 --- /dev/null +++ b/simf/u64_test.simf @@ -0,0 +1,37 @@ +use crate::lib::u64::{checked_add_64, safe_add_64, checked_sub_64, safe_sub_64, checked_mul_64, safe_mul_64, checked_div_64, safe_div_64}; +use crate::lib::asserts::{assert_none_64, assert_eq_64}; +use crate::helper::if_test_this_function; + +/// Asserts a `checked_*` result equals the expected Option. +/// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +/// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert_none_64(result), + Some(e: u64) => assert_eq_64(unwrap(result), e), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u64 = witness::FIRST_ARG; + let b: u64 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_64(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_64(safe_add_64(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_64(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_64(safe_sub_64(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_64(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_64(safe_mul_64(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_64(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_64(safe_div_64(a, b), unwrap(expected))); }, false => (), }; + +} diff --git a/simf/u8_mock.simf b/simf/u8_mock.simf deleted file mode 100644 index d45fcd3..0000000 --- a/simf/u8_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -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}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u8 = witness::FIRST_ARG; - let second_arg: u8 = witness::SECOND_ARG; - let result: u8 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_add_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_add_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_add_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_add_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_sub_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_sub_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_sub_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_sub_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_mul_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_mul_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_mul_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_mul_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_div_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_div_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_div_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_div_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u8_test.simf b/simf/u8_test.simf new file mode 100644 index 0000000..dfd7b25 --- /dev/null +++ b/simf/u8_test.simf @@ -0,0 +1,37 @@ +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}; +use crate::lib::asserts::{assert_none_8, assert_eq_8}; +use crate::helper::if_test_this_function; + +/// Asserts a `checked_*` result equals the expected Option. +/// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +/// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert_none_8(result), + Some(e: u8) => assert_eq_8(unwrap(result), e), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u8 = witness::FIRST_ARG; + let b: u8 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_8(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_8(safe_add_8(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_8(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_8(safe_sub_8(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_8(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_8(safe_mul_8(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_8(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_8(safe_div_8(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index a13a988..5c2e82f 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -1,16 +1,16 @@ -use simplex::simplicityhl::elements::Script; +mod common; -use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; +use rand::Rng; -use simplicityhl_std::artifacts::asserts_mock::AssertsMockProgram; -use simplicityhl_std::artifacts::asserts_mock::derived_asserts_mock::{ - AssertsMockArguments, AssertsMockWitness, -}; - -mod helper; +use common::core::{Expect, run}; -use crate::helper::{cast_to_bool, generate_uints_in_one_range}; +use simplicityhl_std::artifacts::asserts_test::AssertsTestProgram; +use simplicityhl_std::artifacts::asserts_test::derived_asserts_test::{ + AssertsTestArguments, AssertsTestWitness, +}; +// Dispatch indices — must match the `if_test_this_function(N, ..)` arms in +// simf/asserts_test.simf. enum FunctionToTest { AssertEq8, AssertEq16, @@ -32,42 +32,36 @@ const DEFAULT_SOME_U64: Option = Some(0); const DEFAULT_SOME_U128: Option = Some(0); const DEFAULT_SOME_U256: Option<[u8; 32]> = Some([0; 32]); -pub enum IfTestSameValues { - DifferentValues, - SameValues, +fn program() -> AssertsTestProgram { + AssertsTestProgram::new(AssertsTestArguments {}) } -pub enum IfTestNoneValue { - NotNoneValue, - NoneValue, -} - -fn get_asserts_test_script(context: &simplex::TestContext) -> (AssertsMockProgram, Script) { - let arguments = AssertsMockArguments {}; - let asserts_program = AssertsMockProgram::new(arguments); +/// Returns two values in `[min, max]` that are equal when `same`, distinct otherwise. +pub fn generate_uints_in_one_range(same: bool, min_val: u128, max_val: u128) -> (u128, u128) { + let some_u = rand::thread_rng().gen_range(min_val..=max_val); - let asserts_script = asserts_program.get_script_pubkey(context.get_network()); - - (asserts_program, asserts_script) -} + if same { + return (some_u, some_u); + } -fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { - let signer = context.get_default_signer(); + assert!( + min_val != max_val, + "cannot generate distinct values in a single-value range" + ); - let (_, asserts_script) = get_asserts_test_script(context); + let mut other_u = rand::thread_rng().gen_range(min_val..=max_val); - let tx_receipt = signer.send(asserts_script.clone(), 50)?; - println!("Broadcast: {}", tx_receipt); + while other_u == some_u { + other_u = rand::thread_rng().gen_range(min_val..=max_val); + } - Ok(()) + (some_u, other_u) } -fn generate_test_witness( - function_index: FunctionToTest, - if_same_values: bool, - if_none_value: bool, -) -> AssertsMockWitness { - let mut witness: AssertsMockWitness = AssertsMockWitness { +/// Builds the witness for one assert call. `same` controls the two `assert_eq` +/// args; `none` makes the single `assert_none` arg `None`. +fn build_witness(function: FunctionToTest, same: bool, none: bool) -> AssertsTestWitness { + let mut witness = AssertsTestWitness { function_index: 0, first_arg_u8: DEFAULT_SOME_U8, second_arg_u8: DEFAULT_SOME_U8, @@ -83,500 +77,317 @@ fn generate_test_witness( second_arg_u256: DEFAULT_SOME_U256, }; - match function_index { + match function { FunctionToTest::AssertEq8 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); - - (witness.first_arg_u8, witness.second_arg_u8) = - (Some(first_arg as u8), Some(second_arg as u8)); + let (a, b) = generate_uints_in_one_range(same, 0, u8::MAX as u128); + (witness.first_arg_u8, witness.second_arg_u8) = (Some(a as u8), Some(b as u8)); } FunctionToTest::AssertEq16 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u16::MAX as u128); - - (witness.first_arg_u16, witness.second_arg_u16) = - (Some(first_arg as u16), Some(second_arg as u16)); + let (a, b) = generate_uints_in_one_range(same, 0, u16::MAX as u128); + (witness.first_arg_u16, witness.second_arg_u16) = (Some(a as u16), Some(b as u16)); } FunctionToTest::AssertEq32 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u32::MAX as u128); - - (witness.first_arg_u32, witness.second_arg_u32) = - (Some(first_arg as u32), Some(second_arg as u32)); + let (a, b) = generate_uints_in_one_range(same, 0, u32::MAX as u128); + (witness.first_arg_u32, witness.second_arg_u32) = (Some(a as u32), Some(b as u32)); } FunctionToTest::AssertEq64 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u64::MAX as u128); - - (witness.first_arg_u64, witness.second_arg_u64) = - (Some(first_arg as u64), Some(second_arg as u64)); + let (a, b) = generate_uints_in_one_range(same, 0, u64::MAX as u128); + (witness.first_arg_u64, witness.second_arg_u64) = (Some(a as u64), Some(b as u64)); } FunctionToTest::AssertEq256 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); - + let (a, b) = generate_uints_in_one_range(same, 0, u8::MAX as u128); (witness.first_arg_u256, witness.second_arg_u256) = - (Some([first_arg as u8; 32]), Some([second_arg as u8; 32])); + (Some([a as u8; 32]), Some([b as u8; 32])); } FunctionToTest::AssertNone8 => { - if if_none_value { + if none { witness.first_arg_u8 = None; - }; + } } FunctionToTest::AssertNone16 => { - if if_none_value { + if none { witness.first_arg_u16 = None; - }; + } } FunctionToTest::AssertNone32 => { - if if_none_value { + if none { witness.first_arg_u32 = None; - }; + } } FunctionToTest::AssertNone64 => { - if if_none_value { + if none { witness.first_arg_u64 = None; - }; + } } FunctionToTest::AssertNone128 => { - if if_none_value { + if none { witness.first_arg_u128 = None; - }; + } } FunctionToTest::AssertNone256 => { - if if_none_value { + if none { witness.first_arg_u256 = None; - }; + } } } - witness.function_index = function_index as u8; + witness.function_index = function as u8; witness } -fn spend_script( +fn run_assert( context: &simplex::TestContext, - function_index: FunctionToTest, - if_same_values: IfTestSameValues, - if_none_value: IfTestNoneValue, + function: FunctionToTest, + same: bool, + none: bool, + expect: Expect, ) -> anyhow::Result<()> { - let signer = context.get_default_signer(); - let provider = context.get_default_provider(); - - let (asserts_program, asserts_script) = get_asserts_test_script(context); - - let asserts_utxos = provider.fetch_scripthash_utxos(&asserts_script)?; - - let mut ft = FinalTransaction::new(); - - let witness: AssertsMockWitness = generate_test_witness( - function_index, - cast_to_bool(if_same_values as u8), - cast_to_bool(if_none_value as u8), - ); - - ft.add_program_input( - PartialInput::new(asserts_utxos[0].clone()), - ProgramInput::new( - Box::new(asserts_program.as_ref().clone()), - Box::new(witness.clone()), - ), - RequiredSignature::None, - ); - - let tx_receipt = signer.broadcast(&ft)?; - println!("Broadcast: {}", tx_receipt); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq8, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq16, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq32, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq64, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq256, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertNone8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_none_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) + run( + context, + program(), + build_witness(function, same, none), + expect, + ) } -#[simplex::test] -fn assert_none_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_none_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} +mod asserts_test { + use super::*; -#[simplex::test] -fn assert_none_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} + // ---------- assert_eq: happy = equal args, unhappy = distinct args ---------- + #[simplex::test] + fn assert_eq_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert(&context, FunctionToTest::AssertEq8, true, false, Expect::Ok) + } -#[simplex::test] -fn assert_none_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq8, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + #[simplex::test] + fn assert_eq_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq16, + true, + false, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_eq_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq16, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_eq_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq32, + true, + false, + Expect::Ok, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_eq_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq32, + false, + false, + Expect::AssertFailed, + ) + } -#[simplex::test] -fn assert_none_128_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq64, + true, + false, + Expect::Ok, + ) + } - spend_script( - &context, - FunctionToTest::AssertNone128, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; + #[simplex::test] + fn assert_eq_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq64, + false, + false, + Expect::AssertFailed, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_eq_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq256, + true, + false, + Expect::Ok, + ) + } -#[simplex::test] -fn assert_none_128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq256, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone128, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + // ---------- assert_none: happy = None arg, unhappy = Some arg ---------- + #[simplex::test] + fn assert_none_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone8, + false, + true, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_none_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone8, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_none_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone16, + false, + true, + Expect::Ok, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_none_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone16, + false, + false, + Expect::AssertFailed, + ) + } -#[simplex::test] -fn assert_none_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_none_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone32, + false, + true, + Expect::Ok, + ) + } - spend_script( - &context, - FunctionToTest::AssertNone256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; + #[simplex::test] + fn assert_none_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone32, + false, + false, + Expect::AssertFailed, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_none_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone64, + false, + true, + Expect::Ok, + ) + } -#[simplex::test] -fn assert_none_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_none_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone64, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + #[simplex::test] + fn assert_none_128_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone128, + false, + true, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_none_128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone128, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_none_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone256, + false, + true, + Expect::Ok, + ) + } - Ok(()) + #[simplex::test] + fn assert_none_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone256, + false, + false, + Expect::AssertFailed, + ) + } } diff --git a/tests/common/core.rs b/tests/common/core.rs new file mode 100644 index 0000000..9b4d8e2 --- /dev/null +++ b/tests/common/core.rs @@ -0,0 +1,94 @@ +// Each `tests/*.rs` is a separate crate that mounts this module but uses only +// part of it, so per-crate dead-code analysis would warn about the rest. +#![allow(dead_code)] + +use simplex::program::{Program, WitnessTrait}; +use simplex::simplicityhl::elements::Script; +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +#[derive(Clone, Copy)] +pub enum Expect { + /// The spend succeeds. + Ok, + /// A failed `assert!` in the contract. + AssertFailed, + /// Execution reached a pruned branch (e.g. `unwrap(None)`, a `safe_*` overflow). + PrunedBranch, +} + +impl Expect { + /// The exact broadcast error message for a failing expectation (`None` for `Ok`). + fn error_message(self) -> Option<&'static str> { + match self { + Expect::Ok => None, + Expect::AssertFailed => Some("Failed to prune program: Jet failed during execution"), + Expect::PrunedBranch => { + Some("Failed to prune program: Execution reached a pruned branch") + } + } + } +} + +/// Send sats to the program's script so it has a UTXO to spend. +pub fn fund( + context: &simplex::TestContext, + program: &impl AsRef, +) -> anyhow::Result