From 1b6a6816b788252409ccbb7e8d72ba9ea4ccf565 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Tue, 16 Jun 2026 19:51:59 +0200 Subject: [PATCH] chore: migrate rust/composite_query to icp-cli MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace dfx.json with icp.yaml using @dfinity/rust@v3.3.0 - Rename canisters: kv_frontend → caller, data_partition → callee - Move each canister into its own subdirectory (caller/, callee/) - Update workspace Cargo.toml to reference new members - Rewrite caller/lib.rs: replace ic_cdk::api::management_canister with ic-cdk-management-canister crate, replace ic_cdk::api::call::call with ic_cdk::call::Call::bounded_wait pattern - Add Makefile with 7 tests covering put, composite query get, get_update, null lookup, multi-partition routing, and lookup composite query - Add rust-toolchain.toml with wasm32-unknown-unknown target - Add rust-composite_query job to composite_query.yml workflow - Delete legacy rust-composite_query-example.yml workflow - Update README with icp-cli deploy instructions and architecture diagram Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/composite_query.yml | 15 + .../rust-composite_query-example.yml | 53 -- rust/composite_query/Cargo.lock | 890 ------------------ rust/composite_query/Cargo.toml | 6 +- rust/composite_query/Makefile | 55 ++ rust/composite_query/README.md | 73 +- rust/composite_query/callee/Cargo.toml | 13 + .../{src/data_partition => callee}/lib.rs | 7 +- rust/composite_query/caller/Cargo.toml | 13 + rust/composite_query/caller/lib.rs | 138 +++ rust/composite_query/dfx.json | 21 - rust/composite_query/icp.yaml | 15 + rust/composite_query/rust-toolchain.toml | 2 + rust/composite_query/src/data_partition.did | 4 - .../src/data_partition/Cargo.toml | 15 - rust/composite_query/src/kv_frontend.did | 6 - .../src/kv_frontend/Cargo.toml | 14 - rust/composite_query/src/kv_frontend/lib.rs | 121 --- 18 files changed, 291 insertions(+), 1170 deletions(-) delete mode 100644 .github/workflows/rust-composite_query-example.yml delete mode 100644 rust/composite_query/Cargo.lock create mode 100644 rust/composite_query/Makefile create mode 100644 rust/composite_query/callee/Cargo.toml rename rust/composite_query/{src/data_partition => callee}/lib.rs (72%) create mode 100644 rust/composite_query/caller/Cargo.toml create mode 100644 rust/composite_query/caller/lib.rs delete mode 100644 rust/composite_query/dfx.json create mode 100644 rust/composite_query/icp.yaml create mode 100644 rust/composite_query/rust-toolchain.toml delete mode 100644 rust/composite_query/src/data_partition.did delete mode 100644 rust/composite_query/src/data_partition/Cargo.toml delete mode 100644 rust/composite_query/src/kv_frontend.did delete mode 100644 rust/composite_query/src/kv_frontend/Cargo.toml delete mode 100644 rust/composite_query/src/kv_frontend/lib.rs diff --git a/.github/workflows/composite_query.yml b/.github/workflows/composite_query.yml index 347b510c77..ead28e2f74 100644 --- a/.github/workflows/composite_query.yml +++ b/.github/workflows/composite_query.yml @@ -6,6 +6,7 @@ on: pull_request: paths: - motoko/composite_query/** + - rust/composite_query/** - .github/workflows/composite_query.yml concurrency: @@ -26,3 +27,17 @@ jobs: icp network start -d icp deploy --cycles 30t make test + + rust-composite_query: + runs-on: ubuntu-24.04 + container: ghcr.io/dfinity/icp-dev-env-rust:1.0.0 + env: + ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: Deploy and test + working-directory: rust/composite_query + run: | + icp network start -d + icp deploy --cycles 30t + make test diff --git a/.github/workflows/rust-composite_query-example.yml b/.github/workflows/rust-composite_query-example.yml deleted file mode 100644 index c676c6c284..0000000000 --- a/.github/workflows/rust-composite_query-example.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: rust-composite_query -on: - push: - branches: - - master - pull_request: - paths: - - rust/composite_query/** - - .github/workflows/provision-darwin.sh - - .github/workflows/provision-linux.sh - - .github/workflows/rust-composite_query-example.yml - - .github/workflows/rust-composite_query-skip.yml - - .ic-commit -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true -jobs: - rust-composite_query-darwin: - runs-on: macos-15 - steps: - - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 - - name: Provision Darwin - run: bash .github/workflows/provision-darwin.sh - - name: Rust composite_query Darwin - run: | - pushd rust/composite_query - dfx start --background - dfx canister create data_partition --no-wallet - dfx build data_partition - dfx canister create kv_frontend --no-wallet - dfx build kv_frontend - dfx canister install kv_frontend - dfx canister call kv_frontend put '(1, 1337)' - dfx canister call kv_frontend get '(1)' | grep '1_337' - popd - rust-composite_query-linux: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 - - name: Provision Linux - run: bash .github/workflows/provision-linux.sh - - name: Rust composite_query Linux - run: | - pushd rust/composite_query - dfx start --background - dfx canister create data_partition --no-wallet - dfx build data_partition - dfx canister create kv_frontend --no-wallet - dfx build kv_frontend - dfx canister install kv_frontend - dfx canister call kv_frontend put '(1, 1337)' - dfx canister call kv_frontend get '(1)' | grep '1_337' - popd diff --git a/rust/composite_query/Cargo.lock b/rust/composite_query/Cargo.lock deleted file mode 100644 index fc0198930a..0000000000 --- a/rust/composite_query/Cargo.lock +++ /dev/null @@ -1,890 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "binaryen" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783bea139d75b6a565b13fab54d12ec4d58724a9458598ad7283d578f4f8777a" -dependencies = [ - "binaryen-sys", -] - -[[package]] -name = "binaryen-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e9636d01b92f2df45dce29c35a9e3724687c1055bb4472fb4b829cc4a5a561" -dependencies = [ - "cc", - "cmake", - "heck 0.3.3", - "regex", -] - -[[package]] -name = "binread" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f" -dependencies = [ - "binread_derive", - "lazy_static", - "rustversion", -] - -[[package]] -name = "binread_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" -dependencies = [ - "either", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[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 = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "candid" -version = "0.10.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253bab4a9be502c82332b60cbeee6202ad0692834efeec95fae9f29db33d692" -dependencies = [ - "anyhow", - "binread", - "byteorder", - "candid_derive", - "hex", - "ic_principal", - "leb128", - "num-bigint", - "num-traits", - "paste", - "pretty", - "serde", - "serde_bytes", - "stacker", - "thiserror", -] - -[[package]] -name = "candid_derive" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de398570c386726e7a59d9887b68763c481477f9a043fb998a2e09d428df1a9" -dependencies = [ - "lazy_static", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "cc" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "clap_lex", - "indexmap", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "data-encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" - -[[package]] -name = "data_partition" -version = "1.0.0" -dependencies = [ - "candid", - "ic-cdk", - "ic-cdk-macros", - "ic-cdk-optimizer", - "ic-stable-structures", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[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 = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "humansize" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" - -[[package]] -name = "ic-cdk" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122efbcb0af5280d408a75a57b7dc6e9d92893bf6ed9cc98fe4dcff51f18b67c" -dependencies = [ - "candid", - "ic-cdk-macros", - "ic0", - "serde", - "serde_bytes", -] - -[[package]] -name = "ic-cdk-macros" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c792bf0d1621c893ccf2bcdeac4ee70121103a03030a1827031a6b3c60488944" -dependencies = [ - "candid", - "proc-macro2", - "quote", - "serde", - "serde_tokenstream", - "syn 2.0.48", -] - -[[package]] -name = "ic-cdk-optimizer" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c8a7064d878355842d64c20a27c68cfee191781cd3ba5b532974ce6f07e05e" -dependencies = [ - "binaryen", - "clap", - "humansize", - "wabt", -] - -[[package]] -name = "ic-stable-structures" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95dce29e3ceb0e6da3e78b305d95365530f2efd2146ca18590c0ef3aa6038568" - -[[package]] -name = "ic0" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de254dd67bbd58073e23dc1c8553ba12fa1dc610a19de94ad2bbcd0460c067f" - -[[package]] -name = "ic_principal" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" -dependencies = [ - "crc32fast", - "data-encoding", - "serde", - "sha2", - "thiserror", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "kv_frontend" -version = "1.0.0" -dependencies = [ - "candid", - "ic-cdk", - "ic-cdk-macros", - "ic-cdk-optimizer", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "libc" -version = "0.2.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pretty" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac98773b7109bc75f475ab5a134c9b64b87e59d776d31098d8f346922396a477" -dependencies = [ - "arrayvec", - "typed-arena", - "unicode-width", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psm" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" -dependencies = [ - "cc", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "serde" -version = "1.0.196" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.196" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "serde_json" -version = "1.0.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_tokenstream" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn 2.0.48", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -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 = "stacker" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wabt" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bef93d5e6c81a293bccf107cf43aa47239382f455ba14869d36695d8963b9c" -dependencies = [ - "serde", - "serde_derive", - "serde_json", - "wabt-sys", -] - -[[package]] -name = "wabt-sys" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a4e043159f63e16986e713e9b5e1c06043df4848565bf672e27c523864c7791" -dependencies = [ - "cc", - "cmake", - "glob", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[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-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/rust/composite_query/Cargo.toml b/rust/composite_query/Cargo.toml index d2ca148272..10b4a1ad9f 100644 --- a/rust/composite_query/Cargo.toml +++ b/rust/composite_query/Cargo.toml @@ -1,5 +1,3 @@ [workspace] -members = [ - "src/data_partition", - "src/kv_frontend" -] \ No newline at end of file +members = ["caller", "callee"] +resolver = "2" diff --git a/rust/composite_query/Makefile b/rust/composite_query/Makefile new file mode 100644 index 0000000000..2fdeb12371 --- /dev/null +++ b/rust/composite_query/Makefile @@ -0,0 +1,55 @@ +.PHONY: test topup + +topup: + icp canister top-up --amount 30t caller + +test: + @echo "=== Test 1: put inserts a key-value pair (also creates callee partitions) ===" + @result=$$(icp canister call caller put '(1 : nat, 1337 : nat)') && \ + echo "$$result" && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 2: put a second value for the same key returns the old value ===" + @result=$$(icp canister call caller put '(1 : nat, 42 : nat)') && \ + echo "$$result" && \ + echo "$$result" | grep -q '1_337' && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 3: get (composite query) retrieves the stored value ===" + @result=$$(icp canister call --query caller get '(1 : nat)') && \ + echo "$$result" && \ + echo "$$result" | grep -q 'opt (42' && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 4: get_update returns the same value via an update call ===" + @result=$$(icp canister call caller get_update '(1 : nat)') && \ + echo "$$result" && \ + echo "$$result" | grep -q 'opt (42' && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 5: get returns null for a missing key ===" + @result=$$(icp canister call --query caller get '(99 : nat)') && \ + echo "$$result" && \ + echo "$$result" | grep -q 'null' && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 6: composite query routes correctly across partitions ===" + @icp canister call caller put '(2 : nat, 100 : nat)' && \ + icp canister call caller put '(3 : nat, 200 : nat)' && \ + icp canister call caller put '(4 : nat, 300 : nat)' && \ + result1=$$(icp canister call --query caller get '(1 : nat)') && \ + result2=$$(icp canister call --query caller get '(2 : nat)') && \ + result3=$$(icp canister call --query caller get '(3 : nat)') && \ + result4=$$(icp canister call --query caller get '(4 : nat)') && \ + echo "$$result1" && echo "$$result2" && echo "$$result3" && echo "$$result4" && \ + echo "$$result1" | grep -q 'opt (42' && \ + echo "$$result2" | grep -q 'opt (100' && \ + echo "$$result3" | grep -q 'opt (200' && \ + echo "$$result4" | grep -q 'opt (300' && \ + echo "PASS" || (echo "FAIL" && exit 1) + + @echo "=== Test 7: lookup (query) returns the partition index and canister ID ===" + @result=$$(icp canister call --query caller lookup '(1 : nat)') && \ + echo "$$result" && \ + echo "$$result" | grep -q '1 :' && \ + echo "PASS" || (echo "FAIL" && exit 1) diff --git a/rust/composite_query/README.md b/rust/composite_query/README.md index f4d7f287bf..98f088670c 100644 --- a/rust/composite_query/README.md +++ b/rust/composite_query/README.md @@ -1,62 +1,57 @@ # Composite queries -## Prerequisites -This example requires an installation of: +On the Internet Computer, regular query functions are fast (no consensus) but have one strict limitation: **they cannot call other canisters**. Composite queries lift this restriction — a `#[query(composite = true)]` function can call query methods on other canisters while keeping the speed benefit of a query call. -- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install/index.mdx). -- [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples` +For more background see [Composite queries](https://docs.internetcomputer.org/guides/canister-calls/parallel-inter-canister-calls/#composite-queries) in the ICP developer docs. -Begin by opening a terminal window. +This example implements a distributed key-value store (`caller`) that shards its entries across five dynamically-installed `callee` child canisters. Looking up a key requires calling the appropriate callee: -## Step 1: Setup the project environment +- `get(k)` — **composite query**: delegates to the correct `callee.get(k)` as a cross-canister query call. Fast, no consensus. +- `get_update(k)` — **update call**: same lookup, but via an update call to the callee. Slower (goes through consensus) but provided here for comparison. -We first need to build the data partition backend canister. +Both functions return the same result; the difference is latency and call semantics. -```bash -cd examples/rust/composite_query -dfx start --background -dfx canister create data_partition --no-wallet -dfx build data_partition +## Architecture + +``` +caller + n = 5 callees ┌── callee 0 (keys 0, 5, 10, …) + key % n routes ────┼── callee 1 (keys 1, 6, 11, …) + ├── callee 2 (keys 2, 7, 12, …) + ├── callee 3 (keys 3, 8, 13, …) + └── callee 4 (keys 4, 9, 14, …) ``` -During the compilation of the fronted canister, the canister's wasm code will be inlined in the frontend canister's wasm code. +`caller.put(k, v)` dynamically installs a `callee` canister if one does not exist for `k % 5`, then stores the entry there via an update call. `caller.get(k)` and `caller.get_update(k)` both route to the same callee via `k % 5`. -```bash -dfx canister create kv_frontend --no-wallet -dfx build kv_frontend -dfx canister install kv_frontend -``` +The `callee` WASM is embedded directly into the `caller` WASM binary at compile time via `include_bytes!`. This means only the `caller` canister needs to be deployed — it installs the `callee` canisters programmatically on first use. -## Step 2: Using the canister +## Build and deploy from the command line -Now we add some key value pairs via the frontend canister. +### Prerequisites -```bash -dfx canister call kv_frontend put '(1:nat, 1337:nat)' -(null) -dfx canister call kv_frontend put '(1:nat, 42:nat)' -(opt (1_337 : nat)) -``` +- icp-cli: `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` -Note that the first call to `put` is slow, since the data partitions have to be created first. +### Install ```bash -dfx canister call kv_frontend get '(1:nat)' -(opt (42 : nat)) +git clone https://github.com/dfinity/examples +cd examples/rust/composite_query ``` -We can also query it via a (duplicate) method by doing update calls: +### Deploy and test ```bash -dfx canister call kv_frontend get_update '(1:nat)' -(opt (42 : nat)) +icp network start -d +icp deploy --cycles 30t +make test +icp network stop ``` -It's also possible to do *two* query calls, first into the frontend and then into the data partition: +> `icp deploy --cycles 30t` is required because `caller` dynamically creates `callee` canisters — it needs extra cycles to fund their installation. If tests fail with an out-of-cycles error, run `make topup`. -```bash -$ dfx canister call kv_frontend lookup '(1: nat)' -(1 : nat, "dmalx-m4aaa-aaaaa-qaanq-cai") -$ dfx canister call dmalx-m4aaa-aaaaa-qaanq-cai get '(1: nat)' --query -(42 : nat) -``` +Note that the first call to `put` is slow, since all five callee partitions are created at that point. + +## Security considerations and best practices + +Refer to the [security best practices](https://docs.internetcomputer.org/guides/security/overview) for information on security and best practices for your ICP app. diff --git a/rust/composite_query/callee/Cargo.toml b/rust/composite_query/callee/Cargo.toml new file mode 100644 index 0000000000..cce59b7e97 --- /dev/null +++ b/rust/composite_query/callee/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "callee" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] +path = "lib.rs" + +[dependencies] +candid = "0.10" +ic-cdk = "0.20" +ic-stable-structures = "0.6" diff --git a/rust/composite_query/src/data_partition/lib.rs b/rust/composite_query/callee/lib.rs similarity index 72% rename from rust/composite_query/src/data_partition/lib.rs rename to rust/composite_query/callee/lib.rs index c7c697ff91..aeec77db0f 100644 --- a/rust/composite_query/src/data_partition/lib.rs +++ b/rust/composite_query/callee/lib.rs @@ -1,4 +1,5 @@ -use ic_cdk_macros::{query, update}; +use ic_cdk::update; +use ic_cdk::query; use ic_stable_structures::{BTreeMap, DefaultMemoryImpl}; use std::cell::RefCell; @@ -9,7 +10,7 @@ thread_local! { #[update] fn put(key: u128, value: u128) -> Option { - ic_cdk::println!("Set in backend for key={} with value={}", key, value); + ic_cdk::println!("Set in callee for key={} with value={}", key, value); STORE.with(|store| store.borrow_mut().insert(key, value)) } @@ -17,7 +18,7 @@ fn put(key: u128, value: u128) -> Option { fn get(key: u128) -> Option { STORE.with(|store| { let r = store.borrow().get(&key); - ic_cdk::println!("Get in backend for key={} - result={:?}", key, r); + ic_cdk::println!("Get in callee for key={} - result={:?}", key, r); r }) } diff --git a/rust/composite_query/caller/Cargo.toml b/rust/composite_query/caller/Cargo.toml new file mode 100644 index 0000000000..9b999d1f15 --- /dev/null +++ b/rust/composite_query/caller/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "caller" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] +path = "lib.rs" + +[dependencies] +candid = "0.10" +ic-cdk = "0.20" +ic-cdk-management-canister = "0.1.1" diff --git a/rust/composite_query/caller/lib.rs b/rust/composite_query/caller/lib.rs new file mode 100644 index 0000000000..867c498c1c --- /dev/null +++ b/rust/composite_query/caller/lib.rs @@ -0,0 +1,138 @@ +use candid::Principal; +use ic_cdk::call::Call; +use ic_cdk::query; +use ic_cdk::update; +use ic_cdk_management_canister::{ + CanisterInstallMode, CanisterSettings, CreateCanisterArgs, InstallCodeArgs, + create_canister_with_extra_cycles, install_code, +}; + +use std::sync::Arc; +use std::sync::RwLock; + +const NUM_PARTITIONS: usize = 5; + +// Inline wasm binary of the callee canister +pub const WASM: &[u8] = + include_bytes!("../../target/wasm32-unknown-unknown/release/callee.wasm"); + +thread_local! { + // A list of canister IDs for data partitions + static CANISTER_IDS: Arc>> = Arc::new(RwLock::new(vec![])); +} + +#[update] +async fn put(key: u128, value: u128) -> Option { + // Create partitions if they don't exist yet + if CANISTER_IDS.with(|canister_ids| canister_ids.read().unwrap().is_empty()) { + for _ in 0..NUM_PARTITIONS { + create_partition_canister().await; + } + } + + let canister_id = get_partition_for_key(key); + ic_cdk::println!( + "Put in caller for key={} .. using callee={}", + key, + canister_id.to_text() + ); + + Call::bounded_wait(canister_id, "put") + .with_args(&(key, value)) + .await + .ok() + .and_then(|r| r.candid::<(Option,)>().ok()) + .and_then(|(v,)| v) +} + +#[query(composite = true)] +async fn get(key: u128) -> Option { + let canister_id = get_partition_for_key(key); + ic_cdk::println!( + "Get in caller for key={} .. using callee={}", + key, + canister_id.to_text() + ); + + Call::bounded_wait(canister_id, "get") + .with_arg(key) + .await + .ok() + .and_then(|r| r.candid::<(Option,)>().ok()) + .and_then(|(v,)| v) +} + +#[update] +async fn get_update(key: u128) -> Option { + let canister_id = get_partition_for_key(key); + ic_cdk::println!( + "Get as update in caller for key={} .. using callee={}", + key, + canister_id.to_text() + ); + + Call::bounded_wait(canister_id, "get") + .with_arg(key) + .await + .ok() + .and_then(|r| r.candid::<(Option,)>().ok()) + .and_then(|(v,)| v) +} + +fn get_partition_for_key(key: u128) -> Principal { + CANISTER_IDS.with(|canister_ids| { + let canister_ids = canister_ids.read().unwrap(); + canister_ids[lookup(key).0 as usize] + }) +} + +#[query(composite = true)] +fn lookup(key: u128) -> (u128, String) { + let r = key % NUM_PARTITIONS as u128; + ( + r, + CANISTER_IDS.with(|canister_ids| { + let canister_ids = canister_ids.read().unwrap(); + canister_ids[r as usize].to_text() + }), + ) +} + +async fn create_partition_canister() { + const T: u128 = 1_000_000_000_000; + + let create_args = CreateCanisterArgs { + settings: Some(CanisterSettings { + controllers: Some(vec![ic_cdk::canister_self()]), + compute_allocation: None, + memory_allocation: None, + freezing_threshold: None, + reserved_cycles_limit: None, + log_visibility: None, + log_memory_limit: None, + wasm_memory_limit: None, + wasm_memory_threshold: None, + environment_variables: None, + }), + }; + + let result = create_canister_with_extra_cycles(&create_args, 10 * T) + .await + .unwrap(); + let canister_id = result.canister_id; + + ic_cdk::println!("Created callee canister {}", canister_id); + + let install_args = InstallCodeArgs { + mode: CanisterInstallMode::Install, + canister_id, + wasm_module: WASM.to_vec(), + arg: vec![], + }; + + install_code(&install_args).await.unwrap(); + + CANISTER_IDS.with(|canister_ids| { + canister_ids.write().unwrap().push(canister_id); + }); +} diff --git a/rust/composite_query/dfx.json b/rust/composite_query/dfx.json deleted file mode 100644 index c056ca0ff8..0000000000 --- a/rust/composite_query/dfx.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "canisters": { - "data_partition": { - "candid": "src/data_partition.did", - "package": "data_partition", - "type": "rust" - }, - "kv_frontend": { - "candid": "src/kv_frontend.did", - "package": "kv_frontend", - "type": "rust" - } - }, - "defaults": { - "build": { - "args": "", - "packtool": "" - } - }, - "version": 1 -} diff --git a/rust/composite_query/icp.yaml b/rust/composite_query/icp.yaml new file mode 100644 index 0000000000..09d4a7530c --- /dev/null +++ b/rust/composite_query/icp.yaml @@ -0,0 +1,15 @@ +networks: + - name: local + mode: managed + +canisters: + - name: caller + recipe: + type: "@dfinity/rust@v3.3.0" + configuration: + package: caller + - name: callee + recipe: + type: "@dfinity/rust@v3.3.0" + configuration: + package: callee diff --git a/rust/composite_query/rust-toolchain.toml b/rust/composite_query/rust-toolchain.toml new file mode 100644 index 0000000000..990104f055 --- /dev/null +++ b/rust/composite_query/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +targets = ["wasm32-unknown-unknown"] diff --git a/rust/composite_query/src/data_partition.did b/rust/composite_query/src/data_partition.did deleted file mode 100644 index 5b0d356187..0000000000 --- a/rust/composite_query/src/data_partition.did +++ /dev/null @@ -1,4 +0,0 @@ -service : { - "put" : (nat, nat) -> (opt nat); - "get" : (nat) -> (opt nat) query; -}; diff --git a/rust/composite_query/src/data_partition/Cargo.toml b/rust/composite_query/src/data_partition/Cargo.toml deleted file mode 100644 index 6e20a22cf5..0000000000 --- a/rust/composite_query/src/data_partition/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "data_partition" -version = "1.0.0" -edition = "2021" - -[lib] -crate-type = ["cdylib"] -path = "lib.rs" - -[dependencies] -candid = "0.10" -ic-cdk = "0.17.1" -ic-cdk-macros = "0.17.1" -ic-cdk-optimizer = "0.3.5" -ic-stable-structures = "0.5.4" diff --git a/rust/composite_query/src/kv_frontend.did b/rust/composite_query/src/kv_frontend.did deleted file mode 100644 index a256163109..0000000000 --- a/rust/composite_query/src/kv_frontend.did +++ /dev/null @@ -1,6 +0,0 @@ -service : { - "put" : (nat, nat) -> (opt nat); - "get" : (nat) -> (opt nat) composite_query; - "get_update" : (nat) -> (opt nat); - "lookup" : (nat) -> (nat, text) query; -}; diff --git a/rust/composite_query/src/kv_frontend/Cargo.toml b/rust/composite_query/src/kv_frontend/Cargo.toml deleted file mode 100644 index f215f2a1ad..0000000000 --- a/rust/composite_query/src/kv_frontend/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "kv_frontend" -version = "1.0.0" -edition = "2021" - -[lib] -crate-type = ["cdylib"] -path = "lib.rs" - -[dependencies] -candid = "0.10" -ic-cdk = "0.17.1" -ic-cdk-macros = "0.17.1" -ic-cdk-optimizer = "0.3.5" diff --git a/rust/composite_query/src/kv_frontend/lib.rs b/rust/composite_query/src/kv_frontend/lib.rs deleted file mode 100644 index f2361b55c2..0000000000 --- a/rust/composite_query/src/kv_frontend/lib.rs +++ /dev/null @@ -1,121 +0,0 @@ -use ic_cdk::api::call::{call}; -use ic_cdk::api::management_canister::main::{CreateCanisterArgument, create_canister, InstallCodeArgument, install_code, CanisterInstallMode}; -use ic_cdk::api::management_canister::provisional::CanisterSettings; -use ic_cdk_macros::{query, update}; -use candid::Principal; - -use std::sync::Arc; -use std::sync::RwLock; - -const NUM_PARTITIONS: usize = 5; - -// Inline wasm binary of data partition canister -pub const WASM: &[u8] = - include_bytes!("../../target/wasm32-unknown-unknown/release/data_partition.wasm"); - -thread_local! { - // A list of canister IDs for data partitions - static CANISTER_IDS: Arc>> = Arc::new(RwLock::new(vec![])); -} - -#[update] -async fn put(key: u128, value: u128) -> Option { - - // Create partitions if they don't exist yet - if CANISTER_IDS.with(|canister_ids| { - let canister_ids = canister_ids.read().unwrap(); - canister_ids.len() == 0 - }) { - for _ in 0..NUM_PARTITIONS { - create_data_partition_canister_from_wasm().await; - } - } - - let canister_id = get_partition_for_key(key); - ic_cdk::println!("Put in frontend for key={} .. using backend={}", key, canister_id.to_text()); - match call(canister_id, "put", (key, value), ).await { - Ok(r) => { - let (res,): (Option,) = r; - res - }, - Err(_) => None, - } -} - -#[query(composite = true)] -async fn get(key: u128) -> Option { - let canister_id = get_partition_for_key(key); - ic_cdk::println!("Get in frontend for key={} .. using backend={}", key, canister_id.to_text()); - match call(canister_id, "get", (key, ), ).await { - Ok(r) => { - let (res,): (Option,) = r; - res - }, - Err(_) => None, - } -} - -#[update] -async fn get_update(key: u128) -> Option { - let canister_id = get_partition_for_key(key); - ic_cdk::println!("Get as update in frontend for key={} .. using backend={}", key, canister_id.to_text()); - match call(canister_id, "get", (key, ), ).await { - Ok(r) => { - let (res,): (Option,) = r; - res - }, - Err(_) => None, - } -} - -fn get_partition_for_key(key: u128) -> Principal { - let canister_id = CANISTER_IDS.with(|canister_ids| { - let canister_ids = canister_ids.read().unwrap(); - canister_ids[lookup(key).0 as usize] - }); - canister_id -} - -#[query(composite = true)] -fn lookup(key: u128) -> (u128, String) { - let r = key % NUM_PARTITIONS as u128; - (r, CANISTER_IDS.with(|canister_ids| { - let canister_ids = canister_ids.read().unwrap(); - canister_ids[r as usize].to_text() - })) -} - -async fn create_data_partition_canister_from_wasm() { - let create_args = CreateCanisterArgument { - settings: Some(CanisterSettings { - controllers: Some(vec![ic_cdk::id()]), - compute_allocation: None, - memory_allocation: None, - freezing_threshold: None, - reserved_cycles_limit: None, - log_visibility: None, - wasm_memory_limit: None, - }) - }; - - const T: u128 = 1_000_000_000_000; - - let canister_record = create_canister(create_args, 10 * T).await.unwrap(); - let canister_id = canister_record.0.canister_id; - - ic_cdk::println!("Created canister {}", canister_id); - - let install_args = InstallCodeArgument { - mode: CanisterInstallMode::Install, - canister_id, - wasm_module: WASM.to_vec(), - arg: vec![], - }; - - install_code(install_args).await.unwrap(); - - CANISTER_IDS.with(|canister_ids| { - let mut canister_ids = canister_ids.write().unwrap(); - canister_ids.push(canister_id); - }); -}