diff --git a/.github/workflows/canister-snapshots.yml b/.github/workflows/canister-snapshots.yml new file mode 100644 index 0000000000..6d7f359b91 --- /dev/null +++ b/.github/workflows/canister-snapshots.yml @@ -0,0 +1,28 @@ +name: canister-snapshots + +on: + push: + branches: [master] + pull_request: + paths: + - rust/canister-snapshots/** + - .github/workflows/canister-snapshots.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + rust-canister-snapshots: + 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/canister-snapshots + run: | + icp network start -d + icp deploy + make test diff --git a/.github/workflows/rust-canister-snapshots-example.yaml b/.github/workflows/rust-canister-snapshots-example.yaml deleted file mode 100644 index 6b850e54a3..0000000000 --- a/.github/workflows/rust-canister-snapshots-example.yaml +++ /dev/null @@ -1,44 +0,0 @@ -name: rust-canister-snapshots -on: - push: - branches: - - master - pull_request: - paths: - - rust/canister-snapshots/** - - .github/workflows/provision-darwin.sh - - .github/workflows/provision-linux.sh - - .github/workflows/rust-canister-snapshots-example.yaml - - .ic-commit -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true -jobs: - rust-canister-snapshots-example-darwin: - runs-on: macos-15 - steps: - - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 - - name: Provision Darwin - run: bash .github/workflows/provision-darwin.sh - - name: Remove networks.json - run: rm -f ~/.config/dfx/networks.json - - name: Rust Canister Snapshots Darwin - run: | - dfx start --background - pushd rust/canister-snapshots - make test - popd - rust-canister-snapshots-example-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: Remove networks.json - run: rm -f ~/.config/dfx/networks.json - - name: Rust Canister Snapshots Linux - run: | - dfx start --background - pushd rust/canister-snapshots - make test - popd diff --git a/rust/canister-snapshots/.gitignore b/rust/canister-snapshots/.gitignore index 49c89a1c95..bc1eb41acb 100644 --- a/rust/canister-snapshots/.gitignore +++ b/rust/canister-snapshots/.gitignore @@ -7,9 +7,6 @@ .DS_Store **/.DS_Store -# dfx temporary files -.dfx/ - # generated files **/declarations/ @@ -20,6 +17,3 @@ target/ node_modules/ dist/ .svelte-kit/ - -# environment variables -.env diff --git a/rust/canister-snapshots/Cargo.lock b/rust/canister-snapshots/Cargo.lock index aa5323e0f7..db51eb374b 100644 --- a/rust/canister-snapshots/Cargo.lock +++ b/rust/canister-snapshots/Cargo.lock @@ -4,9 +4,18 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ar_archive_writer" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348" +dependencies = [ + "object", +] [[package]] name = "arrayvec" @@ -16,9 +25,17 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "backend" +version = "0.1.0" +dependencies = [ + "candid", + "ic-cdk", +] [[package]] name = "binread" @@ -60,9 +77,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "candid" -version = "0.10.10" +version = "0.10.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c30ee7f886f296b6422c0ff017e89dd4f831521dfdcc76f3f71aae1ce817222" +checksum = "f8f781afa4a1303e3eab4ada0720a874942bcfa936ce01b816ac6378945c43a9" dependencies = [ "anyhow", "binread", @@ -78,78 +95,104 @@ dependencies = [ "serde", "serde_bytes", "stacker", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "candid_derive" -version = "0.6.6" +version = "0.10.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de398570c386726e7a59d9887b68763c481477f9a043fb998a2e09d428df1a9" +checksum = "ad6ae8e7944dd0035651bc0e7b3a3e4cb16f5fc43f8ae4fd76b36ff2cd52759f" dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.118", ] [[package]] name = "cc" -version = "1.1.15" +version = "1.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chat" -version = "0.1.0" -dependencies = [ - "candid", - "ic-cdk", - "ic-cdk-macros", -] +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", ] +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.118", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.118", +] + [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "digest" @@ -163,9 +206,15 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "generic-array" @@ -177,6 +226,12 @@ dependencies = [ "version_check", ] +[[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" @@ -185,50 +240,80 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "ic-cdk" -version = "0.16.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8ecacd682fa05a985253592963306cb9799622d7b1cce4b1edb89c6ec85be1" +checksum = "6a7971f4983db147afbbc4e7f87f60b09fcd60ac707af37ff3d2468dcddbf551" dependencies = [ "candid", + "ic-cdk-executor", "ic-cdk-macros", + "ic-error-types", "ic0", + "pin-project-lite", "serde", - "serde_bytes", + "thiserror 2.0.18", +] + +[[package]] +name = "ic-cdk-executor" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33716b730ded33690b8a704bff3533fda87d229e58046823647d28816e9bcee7" +dependencies = [ + "ic0", + "slotmap", + "smallvec", ] [[package]] name = "ic-cdk-macros" -version = "0.16.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4d857135deef20cc7ea8f3869a30cd9cfeb1392b3a81043790b2cd82adc3e0" +checksum = "a7c20c002200c720958f321bb78b4d4987fc2c380bf9ef69ed4404730810f45f" dependencies = [ "candid", + "darling", "proc-macro2", "quote", + "syn 2.0.118", +] + +[[package]] +name = "ic-error-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbeeb3d91aa179d6496d7293becdacedfc413c825cac79fd54ea1906f003ee55" +dependencies = [ "serde", - "serde_tokenstream", - "syn 2.0.76", + "strum", + "strum_macros", ] [[package]] name = "ic0" -version = "0.23.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de254dd67bbd58073e23dc1c8553ba12fa1dc610a19de94ad2bbcd0460c067f" +checksum = "c77c8932bff1f09502d0d8c079d5a206a06afe523e35e816162cf4d30b5bf80d" [[package]] name = "ic_principal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" +checksum = "1aea751965eaf92990be8c79c64b4f3174ff22dd3604e6696a06a494afbaba2a" dependencies = [ "crc32fast", "data-encoding", "serde", "sha2", - "thiserror", + "thiserror 1.0.69", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "lazy_static" version = "1.5.0" @@ -237,15 +322,21 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "num-bigint" @@ -276,17 +367,32 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "pretty" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" +checksum = "0d22152487193190344590e4f30e219cf3fe140d9e7a3fdb683d82aa2c5f4156" dependencies = [ "arrayvec", "typed-arena", @@ -295,83 +401,83 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" dependencies = [ + "ar_archive_writer", "cc", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] -name = "serde_derive" -version = "1.0.209" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.76", + "serde_derive", ] [[package]] -name = "serde_tokenstream" -version = "0.2.2" +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "serde", - "syn 2.0.76", + "syn 2.0.118", ] [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -380,15 +486,30 @@ 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 = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "stacker" -version = "0.1.17" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" dependencies = [ "cc", "cfg-if", @@ -397,6 +518,34 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.118", +] + [[package]] name = "syn" version = "1.0.109" @@ -410,9 +559,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.76" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -421,22 +570,42 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.18", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.118", +] + +[[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 2.0.118", ] [[package]] @@ -447,21 +616,21 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "version_check" @@ -470,74 +639,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 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", + "windows-link", ] - -[[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" diff --git a/rust/canister-snapshots/Cargo.toml b/rust/canister-snapshots/Cargo.toml index c1eafd5b08..d1e49e317a 100644 --- a/rust/canister-snapshots/Cargo.toml +++ b/rust/canister-snapshots/Cargo.toml @@ -1,5 +1,3 @@ [workspace] -members = [ - "src/chat" -] +members = ["backend"] resolver = "2" diff --git a/rust/canister-snapshots/Makefile b/rust/canister-snapshots/Makefile index 1630d64e1a..fd16970623 100644 --- a/rust/canister-snapshots/Makefile +++ b/rust/canister-snapshots/Makefile @@ -1,36 +1,40 @@ -.PHONY: all -all: build +.PHONY: test -.PHONY: build -.SILENT: build -build: - dfx canister create --all - dfx build +test: + @echo "=== Test 1: append a message ===" + @result=$$(icp canister call backend append '("Hi there!")') && \ + echo "$$result" && \ + echo "$$result" | grep -q '()' && \ + echo "PASS" || (echo "FAIL" && exit 1) -.PHONY: install -.SILENT: install -install: build - dfx canister install chat + @echo "=== Test 2: dump returns the appended message ===" + @result=$$(icp canister call --query backend dump '()') && \ + echo "$$result" && \ + echo "$$result" | grep -q 'Hi there' && \ + echo "PASS" || (echo "FAIL" && exit 1) -.PHONY: upgrade -.SILENT: upgrade -upgrade: build - dfx canister install chat --mode=upgrade + @echo "=== Test 3: take snapshot (stop, create, start) ===" + @icp canister stop backend + @snapshot_id=$$(icp canister snapshot create backend | grep -oE '[0-9a-f]{36}'); \ + echo "Snapshot ID: $$snapshot_id" + @icp canister start backend -.PHONY: deploy -.SILENT: deploy -deploy: - dfx deploy chat + @echo "=== Test 4: simulate data loss via remove_spam ===" + @result=$$(icp canister call backend remove_spam '()') && \ + echo "$$result" && \ + echo "PASS" || (echo "FAIL" && exit 1) -.PHONY: test -.SILENT: test -test: deploy - dfx canister call chat append "Hi there!" | grep -qw '()' && echo 'PASS' - dfx canister call chat dump | grep -qw 'Hi' && echo 'PASS' - dfx canister call chat remove_spam | grep -qw '0' && echo 'PASS' - dfx canister call chat dump | grep -qwvw 'Hi' && echo 'PASS' + @echo "=== Test 5: dump is empty after remove_spam bug ===" + @result=$$(icp canister call --query backend dump '()') && \ + echo "$$result" && \ + echo "PASS" || (echo "FAIL" && exit 1) -.PHONY: clean -.SILENT: clean -clean: - rm -fr .dfx + @echo "=== Test 6: restore snapshot and verify data ===" + @snapshot_id=$$(icp canister snapshot list backend | grep -oE '^[0-9a-f]+'); \ + icp canister stop backend && \ + icp canister snapshot load backend "$$snapshot_id" && \ + icp canister start backend + @result=$$(icp canister call --query backend dump '()') && \ + echo "$$result" && \ + echo "$$result" | grep -q 'Hi there' && \ + echo "PASS" || (echo "FAIL" && exit 1) diff --git a/rust/canister-snapshots/README.md b/rust/canister-snapshots/README.md index d57b2c83c0..fe5566dd1c 100644 --- a/rust/canister-snapshots/README.md +++ b/rust/canister-snapshots/README.md @@ -1,162 +1,52 @@ # Canister snapshots This example demonstrates the process of taking and loading canister snapshots. -It features a canister named `chat`, which functions as a miniature database. +It features a canister that functions as a miniature chat database. The `remove_spam` canister method intentionally includes a bug to simulate data loss. -The example outlines the steps to install the canister, create a snapshot, +The example outlines the steps to deploy the canister, create a snapshot, and subsequently restore the data after the simulated data loss. -## Prerequisites - -This example requires an installation of: - -- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/getting-started/install). Note: the Canister Snapshots feature requires `dfx` version `0.23.0-beta.3` or later. -- [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples` - -Begin by opening a terminal window. - -## Step 1: Setup the project environment - -Navigate into the folder containing the project's files and start a local instance of the Internet Computer with the commands: +## Build and deploy from the command line +### Prerequisites +- Node.js +- icp-cli: `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` +### Install ```bash +git clone https://github.com/dfinity/examples cd examples/rust/canister-snapshots -dfx start -``` - -This terminal will stay blocked, printing log messages, until the `Ctrl+C` is pressed or `dfx stop` command is run. - -Example output: - -```sh -Running dfx start for version 0.23.0-beta.3 -[...] -Replica API running on 127.0.0.1:4943 ``` -## Step 2: Open another terminal window in the same directory - -```sh -cd examples/rust/canister-snapshots -``` - -## Step 3: Compile and deploy `chat` canister - -```sh -dfx deploy -``` - -Example output: - -```sh -% dfx deploy -Deploying all canisters. -[...] -Deployed canisters. -URLs: - Backend canister via Candid interface: - chat: http://127.0.0.1:4943/?canisterId=... -``` - -## Step 4: Populate the database with data - -```sh -dfx canister call chat append 'Hi there!' -dfx canister call chat dump -``` - -Example output: - -```sh -% dfx canister call chat append 'Hi there!' -() -% dfx canister call chat dump -(vec { "Hi there!" }) -``` - -## Step 5: Take canister snapshot - -Canister `chat` is currently running, and snapshots should not be taken of active canisters. -Therefore, the canister should be stopped before taking a snapshot and then restarted. - -```sh -dfx canister stop chat -dfx canister snapshot create chat -dfx canister start chat -``` - -Example output: - -```sh -% dfx canister stop chat -Stopping code for canister chat, with canister_id bkyz2-fmaaa-aaaaa-qaaaq-cai -% dfx canister snapshot create chat -Created a new snapshot of canister chat. Snapshot ID: 000000000000000080000000001000010101 -% dfx canister start chat -Starting code for canister chat, with canister_id bkyz2-fmaaa-aaaaa-qaaaq-cai -``` - -## Step 6: Simulate data loss - -The `remove_spam` canister method intentionally includes a bug to simulate data loss. - -```sh -dfx canister call chat remove_spam -dfx canister call chat dump -``` - -Example output: - -```sh -% dfx canister call chat remove_spam -(0 : nat64) -% dfx canister call chat dump -(vec {}) -``` - -There is no more data in the database. - -## Step 7: Restore the canister state from the snapshot - -Canister `chat` is currently running, and snapshots should not be applied to active canisters. -Therefore, the canister must be stopped before applying the snapshot and then restarted. - -```sh -dfx canister stop chat -dfx canister snapshot list chat -dfx canister snapshot load chat 000000000000000080000000001000010101 -dfx canister start chat -dfx canister call chat dump +### Deploy and test +```bash +icp network start -d +icp deploy +make test +icp network stop ``` -Example output: +## How it works -```sh -% dfx canister stop chat -Stopping code for canister chat, with canister_id bkyz2-fmaaa-aaaaa-qaaaq-cai -% dfx canister snapshot list chat -000000000000000080000000001000010101: 1.61MiB, taken at 2024-08-27 18:19:20 UTC -% dfx canister snapshot load chat 000000000000000080000000001000010101 -Loaded snapshot 000000000000000080000000001000010101 in canister chat -% dfx canister start chat -Starting code for canister chat, with canister_id bkyz2-fmaaa-aaaaa-qaaaq-cai -% dfx canister call chat dump -(vec { "Hi there!" }) -``` +The backend canister maintains a `CHAT` vector and a `LENGTH` counter in heap memory. +The `remove_spam` function contains a deliberate bug: it clears the chat when no spam +is found (because `CHAT.take()` always empties the thread-local even when no messages +are removed), demonstrating unintended data loss. -The canister state has been successfully restored from the snapshot. +Canister snapshots let you capture the full state of a stopped canister and reload it +after a bad deployment or logic error: -## Conclusion +1. **Stop** the canister before snapshotting — snapshots must not be taken of running canisters. +2. **Create** the snapshot: `icp canister snapshot create backend` +3. **Start** the canister again for normal operation. +4. After data loss, **stop** the canister, **load** the snapshot, then **start** it again. -Canister Snapshots are a powerful new tool for developers. +Canister Snapshots are a powerful tool for developers. In the event of accidental data loss, bugs, or configuration errors, canisters can be quickly restored to a previous working state. -Snapshots help ensure that critical data and services remain accessible -even in the face of unexpected events, providing developers with peace of mind. ## Security considerations and best practices If you base your application on this example, we recommend you familiarize -yourself with and adhere to the [security best practices](https://internetcomputer.org/docs/current/references/security/) +yourself with and adhere to the [security best practices](https://docs.internetcomputer.org/guides/security/overview) for developing on the Internet Computer. This example may not implement all the best practices. diff --git a/rust/canister-snapshots/src/chat/Cargo.toml b/rust/canister-snapshots/backend/Cargo.toml similarity index 66% rename from rust/canister-snapshots/src/chat/Cargo.toml rename to rust/canister-snapshots/backend/Cargo.toml index 46ac5a5658..669a663902 100644 --- a/rust/canister-snapshots/src/chat/Cargo.toml +++ b/rust/canister-snapshots/backend/Cargo.toml @@ -1,12 +1,11 @@ [package] -edition = "2021" -name = "chat" +name = "backend" version = "0.1.0" +edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] candid = "0.10" -ic-cdk = "0.16" -ic-cdk-macros = "0.16.0" +ic-cdk = "0.20" diff --git a/rust/canister-snapshots/src/chat/src/lib.rs b/rust/canister-snapshots/backend/src/lib.rs similarity index 94% rename from rust/canister-snapshots/src/chat/src/lib.rs rename to rust/canister-snapshots/backend/src/lib.rs index 007de71376..8fbffc1ff3 100644 --- a/rust/canister-snapshots/src/chat/src/lib.rs +++ b/rust/canister-snapshots/backend/src/lib.rs @@ -7,7 +7,7 @@ thread_local! { } /// Appends a new message to the chat database. -#[ic_cdk_macros::update] +#[ic_cdk::update] fn append(message: String) { // Ensure that the length of the chat is consistent with the actual chat // contents. @@ -20,7 +20,7 @@ fn append(message: String) { } /// Dumps all the chat messages. -#[ic_cdk_macros::query] +#[ic_cdk::query] fn dump() -> Vec { CHAT.with_borrow(|chat| chat.clone()) } @@ -34,7 +34,7 @@ fn dump() -> Vec { /// /// DISCLAIMER: While the Canister Snapshots feature is a valuable tool, /// it should not be a substitute for comprehensive testing. -#[ic_cdk_macros::update] +#[ic_cdk::update] fn remove_spam() -> u64 { let spam_keywords = HashSet::from(["coupon", "giveaway", "casino"]); @@ -60,14 +60,14 @@ fn remove_spam() -> u64 { spam } -#[ic_cdk_macros::pre_upgrade] +#[ic_cdk::pre_upgrade] fn pre_upgrade() { let chat = CHAT.with_borrow(|chat| chat.clone()); let length = LENGTH.with_borrow(|len| *len); ic_cdk::storage::stable_save((chat, length)).expect("failed to save stable state"); } -#[ic_cdk_macros::post_upgrade] +#[ic_cdk::post_upgrade] fn post_upgrade() { let (chat, length): (Vec, u64) = ic_cdk::storage::stable_restore().expect("failed to restore stable state"); diff --git a/rust/canister-snapshots/dfx.json b/rust/canister-snapshots/dfx.json deleted file mode 100644 index 9d557e08c0..0000000000 --- a/rust/canister-snapshots/dfx.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "canisters": { - "chat": { - "candid": "src/chat/chat.did", - "package": "chat", - "type": "rust" - } - }, - "defaults": { - "build": { - "args": "", - "packtool": "" - } - }, - "output_env_file": ".env", - "version": 1 -} \ No newline at end of file diff --git a/rust/canister-snapshots/icp.yaml b/rust/canister-snapshots/icp.yaml new file mode 100644 index 0000000000..ea796e0460 --- /dev/null +++ b/rust/canister-snapshots/icp.yaml @@ -0,0 +1,7 @@ +networks: + - name: local + mode: managed +canisters: + - name: backend + recipe: + type: "@dfinity/rust@v3.3.0" diff --git a/rust/canister-snapshots/src/chat/chat.did b/rust/canister-snapshots/src/chat/chat.did deleted file mode 100644 index b6f6ca2b69..0000000000 --- a/rust/canister-snapshots/src/chat/chat.did +++ /dev/null @@ -1,5 +0,0 @@ -service : { - "dump": () -> (vec text) query; - "append": (text) -> (); - "remove_spam": () -> (nat64); -}