From 63cc3329f8a05004dd332e649526b4e20f0ca666 Mon Sep 17 00:00:00 2001 From: keinberger Date: Wed, 22 Apr 2026 08:34:26 +0300 Subject: [PATCH] chore: migrate tutorials to v14 --- .github/workflows/doc-tests.yml | 2 +- .gitignore | 3 +- docs/Cargo.lock | 4992 +++++++++++++++++ docs/Cargo.toml | 8 +- docs/src/miden-bank/00-project-setup.md | 41 +- docs/src/miden-bank/01-account-components.md | 111 +- .../miden-bank/02-constants-constraints.md | 83 +- docs/src/miden-bank/03-asset-management.md | 110 +- docs/src/miden-bank/04-note-scripts.md | 69 +- docs/src/miden-bank/06-transaction-scripts.md | 27 +- docs/src/miden-bank/07-output-notes.md | 195 +- docs/src/miden-bank/08-complete-flows.md | 89 +- docs/src/miden_node_setup.md | 5 +- .../rust-client/counter_contract_tutorial.md | 64 +- .../src/rust-client/create_deploy_tutorial.md | 49 +- .../creating_notes_in_masm_tutorial.md | 144 +- docs/src/rust-client/custom_note_how_to.md | 71 +- .../rust-client/delegated_proving_tutorial.md | 25 +- .../foreign_procedure_invocation_tutorial.md | 355 +- .../rust-client/mappings_in_masm_how_to.md | 23 +- .../mint_consume_create_tutorial.md | 45 +- .../network_transactions_tutorial.md | 122 +- docs/src/rust-client/oracle_tutorial.md | 54 +- .../public_account_interaction_tutorial.md | 42 +- .../unauthenticated_note_how_to.md | 115 +- .../web-client/counter_contract_tutorial.md | 71 +- docs/src/web-client/create_deploy_tutorial.md | 52 +- .../creating_multiple_notes_tutorial.md | 90 +- .../foreign_procedure_invocation_tutorial.md | 247 +- docs/src/web-client/index.md | 8 +- .../mint_consume_create_tutorial.md | 110 +- docs/src/web-client/react_wallet_tutorial.md | 56 +- docs/src/web-client/setup_guide.md | 256 + .../web-client/unauthenticated_note_how_to.md | 125 +- examples/miden-bank/Cargo.lock | 2595 ++++++--- .../contracts/bank-account/Cargo.lock | 1410 +++-- .../contracts/bank-account/Cargo.toml | 2 +- .../contracts/bank-account/src/lib.rs | 85 +- .../contracts/deposit-note/Cargo.lock | 1410 +++-- .../contracts/deposit-note/Cargo.toml | 2 +- .../contracts/init-tx-script/Cargo.lock | 1410 +++-- .../contracts/init-tx-script/Cargo.toml | 2 +- .../withdraw-request-note/Cargo.lock | 1410 +++-- .../withdraw-request-note/Cargo.toml | 2 +- .../withdraw-request-note/src/lib.rs | 33 +- examples/miden-bank/integration/Cargo.toml | 14 +- .../miden-bank/integration/src/bin/deposit.rs | 6 +- .../integration/src/bin/initialize.rs | 32 +- .../miden-bank/integration/src/helpers.rs | 244 +- .../integration/tests/deposit_test.rs | 133 +- .../integration/tests/withdraw_test.rs | 92 +- masm/accounts/auth/no_auth.masm | 6 +- masm/accounts/count_reader.masm | 12 +- masm/accounts/oracle_reader.masm | 6 +- masm/notes/hash_preimage_note.masm | 26 +- masm/notes/iterative_output_note.masm | 70 +- masm/scripts/reader_script.masm | 13 +- rust-client/Cargo.lock | 2268 +++++--- rust-client/Cargo.toml | 8 +- .../src/bin/counter_contract_deploy.rs | 31 +- rust-client/src/bin/counter_contract_fpi.rs | 109 +- .../src/bin/counter_contract_increment.rs | 27 +- .../src/bin/create_mint_consume_send.rs | 31 +- rust-client/src/bin/delegated_prover.rs | 17 +- rust-client/src/bin/hash_preimage_note.rs | 31 +- rust-client/src/bin/mapping_example.rs | 35 +- .../src/bin/network_notes_counter_contract.rs | 54 +- rust-client/src/bin/note_creation_in_masm.rs | 39 +- rust-client/src/bin/oracle_data_query.rs | 47 +- .../src/bin/unauthenticated_note_transfer.rs | 37 +- web-client/app/page.tsx | 2 +- web-client/lib/createMintConsume.ts | 25 +- web-client/lib/foreignProcedureInvocation.ts | 32 +- web-client/lib/incrementCounterContract.ts | 13 +- web-client/lib/masm/count_reader.masm | 11 +- web-client/lib/mintTestnetToAddress.ts | 18 +- .../lib/multiSendWithDelegatedProver.ts | 32 +- web-client/lib/react/createMintConsume.tsx | 8 +- .../react/multiSendWithDelegatedProver.tsx | 6 +- .../lib/react/unauthenticatedNoteTransfer.tsx | 8 +- web-client/lib/unauthenticatedNoteTransfer.ts | 26 +- web-client/next.config.ts | 40 + web-client/package.json | 4 +- web-client/tests/tutorials.spec.ts | 45 +- web-client/yarn.lock | 717 +-- 85 files changed, 14317 insertions(+), 6278 deletions(-) create mode 100644 docs/Cargo.lock create mode 100644 docs/src/web-client/setup_guide.md diff --git a/.github/workflows/doc-tests.yml b/.github/workflows/doc-tests.yml index c7eefeb0..642281c2 100644 --- a/.github/workflows/doc-tests.yml +++ b/.github/workflows/doc-tests.yml @@ -27,5 +27,5 @@ jobs: - name: Run documentation tests run: | rustup update --no-self-update - cargo test --doc --release -- --test-threads=1 + cargo test --doc --release --locked -- --test-threads=1 working-directory: docs diff --git a/.gitignore b/.gitignore index b09721ee..08539f2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ target/ *.dat node/storage/* -docs/Cargo.lock keystore *.sqlite3 @@ -11,3 +10,5 @@ web-client/playwright-report/ web-client/test-results/ **/.DS_Store .DS_Store +.claude/ +.playwright-mcp/ diff --git a/docs/Cargo.lock b/docs/Cargo.lock new file mode 100644 index 00000000..83b87d8e --- /dev/null +++ b/docs/Cargo.lock @@ -0,0 +1,4992 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloy-primitives" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" +dependencies = [ + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "itoa", + "paste", + "ruint", + "rustc-hash", + "sha3", +] + +[[package]] +name = "alloy-sol-macro" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap", + "proc-macro-error2", + "proc-macro2", + "quote", + "sha3", + "syn 2.0.115", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" +dependencies = [ + "const-hex", + "dunce", + "heck", + "macro-string", + "proc-macro2", + "quote", + "syn 2.0.115", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-types" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +dependencies = [ + "backtrace", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii-canvas" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" +dependencies = [ + "term", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link 0.2.1", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[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 = "build-rs" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc87f52297187fb5d25bde3d368f0480f88ac1d8f3cf4c80ac5575435511114" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "const-hex" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" +dependencies = [ + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[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 = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version 0.4.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "deadpool" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" +dependencies = [ + "deadpool-runtime", + "lazy_static", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-runtime" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +dependencies = [ + "tokio", +] + +[[package]] +name = "deadpool-sync" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524bc3df0d57e98ecd022e21ba31166c2625e7d3e5bcc4510efaeeab4abcab04" +dependencies = [ + "deadpool-runtime", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[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 = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "fs-err" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf68cef89750956493a66a10f512b9e58d9db21f2a573c079c0bdf1207a54a7" +dependencies = [ + "autocfg", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[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.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax", + "sha3", + "string_cache", + "term", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" +dependencies = [ + "rustversion", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[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.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libsqlite3-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "logos" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "rustc_version 0.4.1", + "syn 2.0.115", +] + +[[package]] +name = "logos-derive" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miden-agglayer" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4302fc29d77db3d2c6323d1b211e503aafb91db2d572ef30c68829347fe79352" +dependencies = [ + "alloy-sol-types", + "fs-err", + "miden-assembly", + "miden-core", + "miden-core-lib", + "miden-crypto", + "miden-protocol", + "miden-standards", + "miden-utils-sync", + "primitive-types", + "regex", + "thiserror", + "walkdir", +] + +[[package]] +name = "miden-air" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15646ebc95906b2a7cb66711d1e184f53fd6edc2605730bbcf0c2a129f792cf" +dependencies = [ + "miden-core", + "miden-crypto", + "miden-utils-indexing", + "thiserror", + "tracing", +] + +[[package]] +name = "miden-assembly" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6013b3a390e0dcb29242f4480a7727965887bbf0903466c88f362b4cb20c0e" +dependencies = [ + "env_logger", + "log", + "miden-assembly-syntax", + "miden-core", + "miden-mast-package", + "miden-package-registry", + "miden-project", + "smallvec", + "thiserror", +] + +[[package]] +name = "miden-assembly-syntax" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "996156b8f7c5fe6be17dea71089c6d7985c2dec1e3a4fec068b1dfc690e25df5" +dependencies = [ + "aho-corasick", + "env_logger", + "lalrpop", + "lalrpop-util", + "log", + "miden-core", + "miden-debug-types", + "miden-utils-diagnostics", + "midenc-hir-type", + "proptest", + "proptest-derive", + "regex", + "rustc_version 0.4.1", + "semver 1.0.27", + "serde", + "smallvec", + "thiserror", +] + +[[package]] +name = "miden-block-prover" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde56bcea3cebe307786a856e204d84e7987c318e5a2909bcbb655d16286ce31" +dependencies = [ + "miden-protocol", + "thiserror", +] + +[[package]] +name = "miden-client" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49957f76717961769c911237113bb9c1841c3b13970c15ca09a0ae639c33fc45" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "futures", + "getrandom 0.3.4", + "gloo-timers", + "hex", + "miden-node-proto-build", + "miden-note-transport-proto-build", + "miden-protocol", + "miden-remote-prover-client", + "miden-standards", + "miden-testing", + "miden-tx", + "miette", + "prost", + "prost-types", + "rand 0.9.2", + "serde", + "serde_json", + "thiserror", + "tokio", + "tonic", + "tonic-health", + "tonic-prost", + "tonic-prost-build", + "tonic-web-wasm-client", + "tracing", + "uuid", + "web-sys", +] + +[[package]] +name = "miden-client-sqlite-store" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab146099a4bf8319f5cac47e110eca7d3e3caa9d2fc354693458f905f4750a7" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "deadpool", + "deadpool-sync", + "miden-client", + "miden-protocol", + "rusqlite", + "rusqlite_migration", + "thiserror", + "tokio", +] + +[[package]] +name = "miden-core" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdec54a321cdf3d23e9ef615e91cb858038c6b4d4202507bdec048fc6d7763e4" +dependencies = [ + "derive_more", + "itertools", + "miden-crypto", + "miden-debug-types", + "miden-formatting", + "miden-utils-core-derive", + "miden-utils-indexing", + "miden-utils-sync", + "num-derive", + "num-traits", + "proptest", + "proptest-derive", + "serde", + "thiserror", +] + +[[package]] +name = "miden-core-lib" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621e8fa911a790bcf3cd3aedce80bc10922a19d6181f08ff3ca078f955cff70b" +dependencies = [ + "env_logger", + "fs-err", + "miden-assembly", + "miden-core", + "miden-crypto", + "miden-package-registry", + "miden-processor", + "miden-utils-sync", + "thiserror", +] + +[[package]] +name = "miden-crypto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0a034a460e27723dcfdf25effffab84331c3b46b13e7a1bd674197cc71bfe" +dependencies = [ + "blake3", + "cc", + "chacha20poly1305", + "curve25519-dalek", + "ed25519-dalek", + "flume", + "glob", + "hkdf", + "k256", + "miden-crypto-derive", + "miden-field", + "miden-serde-utils", + "num", + "num-complex", + "p3-blake3", + "p3-challenger", + "p3-dft", + "p3-goldilocks", + "p3-keccak", + "p3-matrix", + "p3-maybe-rayon", + "p3-miden-lifted-stark", + "p3-symmetric", + "p3-util", + "rand 0.9.2", + "rand_chacha", + "rand_core 0.9.3", + "rand_hc", + "rayon", + "serde", + "sha2", + "sha3", + "subtle", + "thiserror", + "x25519-dalek", +] + +[[package]] +name = "miden-crypto-derive" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8bf6ebde028e79bcc61a3632d2f375a5cc64caa17d014459f75015238cb1e08" +dependencies = [ + "quote", + "syn 2.0.115", +] + +[[package]] +name = "miden-debug-types" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6e50274d11c80b901cf6c90362de8c98c8c8ad6030c80624d683b63d899a0fb" +dependencies = [ + "memchr", + "miden-crypto", + "miden-formatting", + "miden-miette", + "miden-utils-indexing", + "miden-utils-sync", + "paste", + "serde", + "serde_spanned", + "thiserror", +] + +[[package]] +name = "miden-field" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38011348f4fb4c9e5ce1f471203d024721c00e3b60a91aa91aaefe6738d8b5ea" +dependencies = [ + "miden-serde-utils", + "num-bigint", + "p3-challenger", + "p3-field", + "p3-goldilocks", + "paste", + "rand 0.10.0", + "serde", + "subtle", + "thiserror", +] + +[[package]] +name = "miden-formatting" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e392e0a8c34b32671012b439de35fa8987bf14f0f8aac279b97f8b8cc6e263b" +dependencies = [ + "unicode-width 0.1.14", +] + +[[package]] +name = "miden-mast-package" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc8b2e3447fcde1f0e6b76e5219f129517639772cb02ca543177f0584e315288" +dependencies = [ + "derive_more", + "miden-assembly-syntax", + "miden-core", + "miden-debug-types", + "serde", + "thiserror", +] + +[[package]] +name = "miden-miette" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eef536978f24a179d94fa2a41e4f92b28e7d8aab14b8d23df28ad2a3d7098b20" +dependencies = [ + "cfg-if", + "futures", + "indenter", + "lazy_static", + "miden-miette-derive", + "owo-colors", + "regex", + "rustc_version 0.2.3", + "rustversion", + "serde_json", + "spin 0.9.8", + "strip-ansi-escapes", + "syn 2.0.115", + "textwrap", + "thiserror", + "trybuild", + "unicode-width 0.1.14", +] + +[[package]] +name = "miden-miette-derive" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86a905f3ea65634dd4d1041a4f0fd0a3e77aa4118341d265af1a94339182222f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "miden-node-proto-build" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9beefe1d90ebeb044b15a8c764eb7031d892f9ae357ac9c8847c1cab3b07045a" +dependencies = [ + "build-rs", + "fs-err", + "miette", + "protox", + "tonic-prost-build", +] + +[[package]] +name = "miden-note-transport-proto-build" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec23738a2eee393524a849a8dce982ad824050cc54abde145d4fb62b92c84198" +dependencies = [ + "fs-err", + "miette", + "protox", + "tonic-prost-build", +] + +[[package]] +name = "miden-package-registry" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969ba3942052e52b3968e34dbd1c52c707e75777ee42ebdae2c8f57af56cf6cf" +dependencies = [ + "miden-assembly-syntax", + "miden-core", + "miden-mast-package", + "pubgrub", + "serde", + "smallvec", + "thiserror", +] + +[[package]] +name = "miden-processor" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ec6cecbf22bd92b73a931ee80b424e46b8b7cdf4f2f3c364c25c5c15d2840da" +dependencies = [ + "itertools", + "miden-air", + "miden-core", + "miden-debug-types", + "miden-utils-diagnostics", + "miden-utils-indexing", + "paste", + "rayon", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "miden-project" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3840520c01881534fbbceb6b3687ec1c407fbaf310a35ce415fd3510abc52fdb" +dependencies = [ + "miden-assembly-syntax", + "miden-core", + "miden-mast-package", + "miden-package-registry", + "serde", + "serde-untagged", + "thiserror", + "toml 1.1.2+spec-1.1.0", +] + +[[package]] +name = "miden-protocol" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e860cc978d3467297de076e9bd22f0573b82ef73a3d223d6bb957731a45b8164" +dependencies = [ + "bech32", + "fs-err", + "getrandom 0.3.4", + "miden-assembly", + "miden-assembly-syntax", + "miden-core", + "miden-core-lib", + "miden-crypto", + "miden-mast-package", + "miden-processor", + "miden-protocol-macros", + "miden-utils-sync", + "miden-verifier", + "rand 0.9.2", + "rand_chacha", + "rand_xoshiro", + "regex", + "semver 1.0.27", + "serde", + "thiserror", + "toml 1.1.2+spec-1.1.0", + "walkdir", +] + +[[package]] +name = "miden-protocol-macros" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4daec4a5a6f050a670a8639e78e017ab11ef0bf2e253b012505f25e6247c13e7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "miden-prover" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb2c94e36f57684d7fa0cd382adeedc1728d502dbbe69ad1c12f4a931f45511" +dependencies = [ + "bincode", + "miden-air", + "miden-core", + "miden-crypto", + "miden-debug-types", + "miden-processor", + "serde", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "miden-remote-prover-client" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf7590551de605a7dc6217d81e76c8f00196dbaeb905cef4239c7bc7725fbeb6" +dependencies = [ + "build-rs", + "fs-err", + "getrandom 0.4.2", + "miden-node-proto-build", + "miden-protocol", + "miden-tx", + "miette", + "prost", + "thiserror", + "tokio", + "tonic", + "tonic-prost", + "tonic-prost-build", + "tonic-web-wasm-client", +] + +[[package]] +name = "miden-serde-utils" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff78082e9b4ca89863e68da01b35f8a4029ee6fd912e39fa41fde4273a7debab" +dependencies = [ + "p3-field", + "p3-goldilocks", +] + +[[package]] +name = "miden-standards" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f455a087f41c30636b45ead961d1e66114d2d20661887b307cede05307eeb942" +dependencies = [ + "fs-err", + "miden-assembly", + "miden-core", + "miden-core-lib", + "miden-processor", + "miden-protocol", + "rand 0.9.2", + "regex", + "thiserror", + "walkdir", +] + +[[package]] +name = "miden-testing" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84430e84c6dee90d9bd92568be1c3082113f0b4b36f9db7933380f0295207f9" +dependencies = [ + "anyhow", + "itertools", + "miden-agglayer", + "miden-assembly", + "miden-block-prover", + "miden-core-lib", + "miden-crypto", + "miden-processor", + "miden-protocol", + "miden-standards", + "miden-tx", + "miden-tx-batch-prover", + "rand 0.9.2", + "rand_chacha", + "thiserror", +] + +[[package]] +name = "miden-tutorials-docs" +version = "0.1.0" +dependencies = [ + "miden-client", + "miden-client-sqlite-store", + "miden-protocol", + "rand 0.9.2", + "rand_chacha", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "miden-tx" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d788795041ce5e6f947a3256314373171e4877c11b86fafeabcec4d8b8628d9" +dependencies = [ + "miden-processor", + "miden-protocol", + "miden-prover", + "miden-standards", + "miden-verifier", + "thiserror", +] + +[[package]] +name = "miden-tx-batch-prover" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce059e2d599266b00708f6f1bff6af5cf82683e76df3ec812c2d1c72e880f943" +dependencies = [ + "miden-protocol", + "miden-tx", +] + +[[package]] +name = "miden-utils-core-derive" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3846c8674ccec0c37005f99c1a599a24790ba2a5e5f4e1c7aec5f456821df835" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "miden-utils-diagnostics" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397f5d1e8679cf17cf7713ffd9654840791a6ed5818b025bbc2fbfdce846579a" +dependencies = [ + "miden-crypto", + "miden-debug-types", + "miden-miette", + "paste", + "tracing", +] + +[[package]] +name = "miden-utils-indexing" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8834e76299686bcce3de1685158aa4cff49b7fa5e0e00a6cc811e8f2cf5775f" +dependencies = [ + "miden-crypto", + "serde", + "thiserror", +] + +[[package]] +name = "miden-utils-sync" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9e9747e9664c1a0997bb040ae291306ea0a1c74a572141ec66cec855c1b0e8" +dependencies = [ + "lock_api", + "loom", + "once_cell", + "parking_lot", +] + +[[package]] +name = "miden-verifier" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4580df640d889c9f3c349cd2268968e44a99a8cf0df6c36ae5b1fb273712b00" +dependencies = [ + "bincode", + "miden-air", + "miden-core", + "miden-crypto", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "midenc-hir-type" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb29d7c049fb69373c7e775e3d4411e63e4ee608bc43826282ba62c6ec9f891" +dependencies = [ + "miden-formatting", + "miden-serde-utils", + "serde", + "serde_repr", + "smallvec", + "thiserror", +] + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + +[[package]] +name = "p3-air" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f2ec9cbfc642fc5173817287c3f8b789d07743b5f7e812d058b7a03e344f9ab" +dependencies = [ + "p3-field", + "p3-matrix", + "tracing", +] + +[[package]] +name = "p3-blake3" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b667f43b19499dd939c9e2553aa95688936a88360d50117dae3c8848d07dbc70" +dependencies = [ + "blake3", + "p3-symmetric", + "p3-util", +] + +[[package]] +name = "p3-challenger" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0b490c745a7d2adeeafff06411814c8078c432740162332b3cd71be0158a76" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-monty-31", + "p3-symmetric", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-commit" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916ae7989d5c3b49f887f5c55b2f9826bdbb81aaebf834503c4145d8b267c829" +dependencies = [ + "itertools", + "p3-field", + "p3-matrix", + "p3-util", + "serde", +] + +[[package]] +name = "p3-dft" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55301e91544440254977108b85c32c09d7ea05f2f0dd61092a2825339906a4a7" +dependencies = [ + "itertools", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "spin 0.10.0", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85affca7fc983889f260655c4cf74163eebb94605f702e4b6809ead707cba54f" +dependencies = [ + "itertools", + "num-bigint", + "p3-maybe-rayon", + "p3-util", + "paste", + "rand 0.10.0", + "serde", + "tracing", +] + +[[package]] +name = "p3-goldilocks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca1081f5c47b940f2d75a11c04f62ea1cc58a5d480dd465fef3861c045c63cd" +dependencies = [ + "num-bigint", + "p3-challenger", + "p3-dft", + "p3-field", + "p3-mds", + "p3-poseidon1", + "p3-poseidon2", + "p3-symmetric", + "p3-util", + "paste", + "rand 0.10.0", + "serde", +] + +[[package]] +name = "p3-keccak" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcf27615ece1995e4fcf4c69740f1cf515d1481367a20b4b3ce7f4f1b8d70f7" +dependencies = [ + "p3-symmetric", + "p3-util", + "tiny-keccak", +] + +[[package]] +name = "p3-matrix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53428126b009071563d1d07305a9de8be0d21de00b57d2475289ee32ffca6577" +dependencies = [ + "itertools", + "p3-field", + "p3-maybe-rayon", + "p3-util", + "rand 0.10.0", + "serde", + "tracing", +] + +[[package]] +name = "p3-maybe-rayon" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082bf467011c06c768c579ec6eb9accb5e1e62108891634cc770396e917f978a" +dependencies = [ + "rayon", +] + +[[package]] +name = "p3-mds" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35209e6214102ea6ec6b8cb1b9c15a9b8e597a39f9173597c957f123bced81b3" +dependencies = [ + "p3-dft", + "p3-field", + "p3-symmetric", + "p3-util", + "rand 0.10.0", +] + +[[package]] +name = "p3-miden-lifted-air" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5c31c65fdc88952d7b301546add9670676e5b878aa0066dd929f107c203b006" +dependencies = [ + "p3-air", + "p3-field", + "p3-matrix", + "p3-util", + "thiserror", +] + +[[package]] +name = "p3-miden-lifted-fri" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9932f1b0a16609a45cd4ee10a4d35412728bc4b38837c7979d7c85d8dcc9fc" +dependencies = [ + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-miden-lmcs", + "p3-miden-transcript", + "p3-util", + "rand 0.10.0", + "thiserror", + "tracing", +] + +[[package]] +name = "p3-miden-lifted-stark" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3956ab7270c3cdd53ca9796d39ae1821984eb977415b0672110f9666bff5d8" +dependencies = [ + "p3-challenger", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-miden-lifted-air", + "p3-miden-lifted-fri", + "p3-miden-lmcs", + "p3-miden-stateful-hasher", + "p3-miden-transcript", + "p3-util", + "thiserror", + "tracing", +] + +[[package]] +name = "p3-miden-lmcs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c46791c983e772136db3d48f102431457451447abb9087deb6c8ce3c1efc86" +dependencies = [ + "p3-commit", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-miden-stateful-hasher", + "p3-miden-transcript", + "p3-symmetric", + "p3-util", + "rand 0.10.0", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "p3-miden-stateful-hasher" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec47a9d9615eb3d9d2a59b00d19751d9ad85384b55886827913d680d912eac6a" +dependencies = [ + "p3-field", + "p3-symmetric", +] + +[[package]] +name = "p3-miden-transcript" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c565647487e4a949f67e6f115b0391d6cb82ac8e561165789939bab23d0ae7" +dependencies = [ + "p3-challenger", + "p3-field", + "serde", + "thiserror", +] + +[[package]] +name = "p3-monty-31" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffa8c99ec50c035020bbf5457c6a729ba6a975719c1a8dd3f16421081e4f650c" +dependencies = [ + "itertools", + "num-bigint", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-mds", + "p3-poseidon1", + "p3-poseidon2", + "p3-symmetric", + "p3-util", + "paste", + "rand 0.10.0", + "serde", + "spin 0.10.0", + "tracing", +] + +[[package]] +name = "p3-poseidon1" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a018b618e3fa0aec8be933b1d8e404edd23f46991f6bf3f5c2f3f95e9413fe9" +dependencies = [ + "p3-field", + "p3-symmetric", + "rand 0.10.0", +] + +[[package]] +name = "p3-poseidon2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256a668a9ba916f8767552f13d0ba50d18968bc74a623bfdafa41e2970c944d0" +dependencies = [ + "p3-field", + "p3-mds", + "p3-symmetric", + "p3-util", + "rand 0.10.0", +] + +[[package]] +name = "p3-symmetric" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c60a71a1507c13611b0f2b0b6e83669fd5b76f8e3115bcbced5ccfdf3ca7807" +dependencies = [ + "itertools", + "p3-field", + "p3-util", + "serde", +] + +[[package]] +name = "p3-util" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b766b9e9254bf3fa98d76e42cf8a5b30628c182dfd5272d270076ee12f0fc0" +dependencies = [ + "rayon", + "serde", + "transpose", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.115", +] + +[[package]] +name = "primitive-types" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721a1da530b5a2633218dc9f75713394c983c352be88d2d7c9ee85e2c4c21794" +dependencies = [ + "fixed-hash", + "uint", +] + +[[package]] +name = "priority-queue" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93980406f12d9f8140ed5abe7155acb10bb1e69ea55c88960b9c2f117445ef96" +dependencies = [ + "equivalent", + "indexmap", + "serde", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bitflags", + "num-traits", + "rand 0.9.2", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "proptest-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.115", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "prost-reflect" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89455ef41ed200cafc47c76c552ee7792370ac420497e551f16123a9135f76e" +dependencies = [ + "logos", + "miette", + "prost", + "prost-types", +] + +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost", +] + +[[package]] +name = "protox" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f25a07a73c6717f0b9bbbd685918f5df9815f7efba450b83d9c9dea41f0e3a1" +dependencies = [ + "bytes", + "miette", + "prost", + "prost-reflect", + "prost-types", + "protox-parse", + "thiserror", +] + +[[package]] +name = "protox-parse" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072eee358134396a4643dff81cfff1c255c9fbd3fb296be14bdb6a26f9156366" +dependencies = [ + "logos", + "miette", + "prost-types", + "thiserror", +] + +[[package]] +name = "pubgrub" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f5df7e552bc7edd075f5783a87fbfc21d6a546e32c16985679c488c18192d83" +dependencies = [ + "indexmap", + "log", + "priority-queue", + "rustc-hash", + "thiserror", + "version-ranges", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "21.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8246feae3db61428fd0bb94285c690b460e4517d83152377543ca802357785f1" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core 0.9.3", +] + +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "rand_core 0.10.0", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + +[[package]] +name = "rand_hc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b363d4f6370f88d62bf586c80405657bde0f0e1b8945d47d2ad59b906cb4f54" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[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.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ruint" +version = "1.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +dependencies = [ + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rusqlite" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "rusqlite_migration" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc9767ae49274bafd3e55be9d30405a033b7a59548327d87fd4971fbb58e264" +dependencies = [ + "log", + "rusqlite", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.27", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[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 = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[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-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[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 2.0.115", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[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 = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[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.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "target-triple" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "term" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2111ef44dae28680ae9752bb89409e7310ca33a8c621ebe7b106cf5c928b3ac0" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +dependencies = [ + "rustix", + "windows-sys 0.60.2", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width 0.2.2", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow 0.7.13", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.1", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +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.1", +] + +[[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 = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "async-trait", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "rustls-native-certs", + "socket2", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "tonic-health" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a82868bf299e0a1d2e8dce0dc33a46c02d6f045b2c1f1d6cc8dc3d0bf1812ef" +dependencies = [ + "prost", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", +] + +[[package]] +name = "tonic-prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.115", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tonic-web-wasm-client" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e21e20b94f808d6f2244a5d960d02c28dd82066abddd2f27019bac0535f310" +dependencies = [ + "base64", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "trybuild" +version = "1.0.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d66678374d835fe847e0dc8348fde2ceb5be4a7ec204437d8367f0d8df266a5" +dependencies = [ + "dissimilar", + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml 0.9.8", +] + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[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 = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-ranges" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3595ffe225639f1e0fd8d7269dcc05d2fbfea93cfac2fea367daf1adb60aae91" +dependencies = [ + "smallvec", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + +[[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 = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[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.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen 0.46.0", +] + +[[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.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.115", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +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 = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver 1.0.27", +] + +[[package]] +name = "web-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[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-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 2.0.115", + "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 2.0.115", + "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", + "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 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/docs/Cargo.toml b/docs/Cargo.toml index 248a3f70..eeb43898 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } -tokio = { version = "1.46", features = ["rt-multi-thread", "net", "macros", "fs"] } +tokio = { version = "1.48", features = ["rt-multi-thread", "net", "macros", "fs"] } rand_chacha = "0.9.0" diff --git a/docs/src/miden-bank/00-project-setup.md b/docs/src/miden-bank/00-project-setup.md index f0da5765..6fda6470 100644 --- a/docs/src/miden-bank/00-project-setup.md +++ b/docs/src/miden-bank/00-project-setup.md @@ -98,7 +98,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -miden = { version = "0.10" } +miden = { version = "0.12" } [package.metadata.component] package = "miden:bank-account" @@ -141,30 +141,30 @@ struct Bank { /// Tracks whether the bank has been initialized (deposits enabled). /// Word layout: [is_initialized (0 or 1), 0, 0, 0] #[storage(description = "initialized")] - initialized: Value, + initialized: StorageValue, /// Maps depositor AccountId -> balance (as Felt). /// We'll use this to track user balances in Part 1. #[storage(description = "balances")] - balances: StorageMap, + balances: StorageMap, } #[component] impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - // Read current value from storage - let current: Word = self.initialized.read(); + // Get current value from storage + let current: Word = self.initialized.get(); // Check not already initialized assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); // Set initialized flag to 1 let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. @@ -174,15 +174,15 @@ impl Bank { /// in at least one public method. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } } ``` This is our starting point with two storage slots: -- `initialized`: A `Value` slot to track whether the bank is ready -- `balances`: A `StorageMap` to track user balances (we'll use this starting in Part 1) +- `initialized`: A `StorageValue` slot to track whether the bank is ready +- `balances`: A `StorageMap` to track user balances (we'll use this starting in Part 1) :::note Compiler Requirement Account components must use WIT binding types (like `AccountId`, `Asset`, etc.) in at least one public method signature for the compiler to generate the required bindings correctly. The `get_balance` method serves this purpose. @@ -209,7 +209,7 @@ edition = "2021" ``` :::info Contracts Are Excluded -In v0.13, contracts are excluded from the Cargo workspace and built independently by `cargo miden`. Each contract specifies its own `miden` dependency directly. Only the `integration` crate remains a workspace member. +In v0.14, contracts are excluded from the Cargo workspace and built independently by `cargo miden`. Each contract specifies its own `miden` dependency directly. Only the `integration` crate remains a workspace member. ::: ## Step 5: Build and Verify @@ -260,25 +260,24 @@ async fn test_bank_account_builds_and_loads() -> anyhow::Result<()> { // Create named storage slots matching the contract's storage layout let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot, Word::default()), - StorageSlot::with_map( - balances_slot, - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // Verify the account was created println!("Bank account created with ID: {:?}", bank_account.id()); diff --git a/docs/src/miden-bank/01-account-components.md b/docs/src/miden-bank/01-account-components.md index c179b052..15e1a300 100644 --- a/docs/src/miden-bank/01-account-components.md +++ b/docs/src/miden-bank/01-account-components.md @@ -22,13 +22,13 @@ By the end of this section, you will have: In Part 0, we created a minimal bank with just an `initialized` flag. Now we'll add balance tracking: ```text -Part 0: Part 1: -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Bank β”‚ β”‚ Bank β”‚ -β”‚ ───────────────── β”‚ ──► β”‚ ──────────────────────── β”‚ -β”‚ initialized (Value)β”‚ β”‚ initialized (Value) β”‚ -β”‚ β”‚ β”‚ balances (StorageMap) β”‚ ◄── NEW -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +Part 0: Part 1: +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Bank β”‚ β”‚ Bank β”‚ +β”‚ ──────────────────────── β”‚ ──► β”‚ ──────────────────────────── β”‚ +β”‚ initialized (StorageValue) β”‚ β”‚ initialized (StorageValue) β”‚ +β”‚ β”‚ β”‚ balances (StorageMap)β”‚ ◄── NEW +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## The #[component] Attribute @@ -60,12 +60,12 @@ struct Bank { /// Tracks whether the bank has been initialized (deposits enabled). /// Word layout: [is_initialized (0 or 1), 0, 0, 0] #[storage(description = "initialized")] - initialized: Value, + initialized: StorageValue, /// Maps depositor AccountId -> balance (as Felt) /// Key: [prefix, suffix, asset_prefix, asset_suffix] #[storage(description = "balances")] - balances: StorageMap, + balances: StorageMap, } ``` @@ -75,44 +75,44 @@ We've added a `StorageMap` that will track each depositor's balance. The compile Miden accounts have storage slots that persist state on-chain. Each slot holds one `Word` (4 Felts = 32 bytes). The Miden Rust compiler provides two abstractions: -### Value Storage +### StorageValue Storage -The `Value` type provides access to a single storage slot: +The `StorageValue` type provides access to a single storage slot: ```rust #[storage(description = "initialized")] -initialized: Value, +initialized: StorageValue, ``` -Use `Value` when you need to store a single `Word` of data. +Use `StorageValue` when you need to store a single `Word` of data. **Reading and writing:** ```rust -// Read returns a Word -let current: Word = self.initialized.read(); +// Get returns a Word +let current: Word = self.initialized.get(); // Check the first element (our flag) -if current[0].as_u64() == 0 { +if current[0].as_canonical_u64() == 0 { // Not initialized } -// Write a new value +// Set a new value let new_value = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); -self.initialized.write(new_value); +self.initialized.set(new_value); ``` :::tip Type Annotations -The `.read()` method requires a type annotation: `let current: Word = self.initialized.read();` +The `.get()` method requires a type annotation: `let current: Word = self.initialized.get();` ::: ### StorageMap -The `StorageMap` type provides key-value storage within a slot: +The `StorageMap` type provides key-value storage within a slot: ```rust #[storage(description = "balances")] -balances: StorageMap, +balances: StorageMap, ``` Use `StorageMap` when you need to store multiple values indexed by keys. @@ -144,12 +144,12 @@ Unlike `Value::read()` which returns a `Word`, `StorageMap::get()` returns a sin Plan your storage layout carefully: -| Name | Type | Purpose | -| ------------- | ------------ | ------------------- | -| `initialized` | `Value` | Initialization flag | -| `balances` | `StorageMap` | Depositor balances | +| Name | Type | Purpose | +| ------------- | ------------------------ | ------------------- | +| `initialized` | `StorageValue` | Initialization flag | +| `balances` | `StorageMap` | Depositor balances | -The `description` attribute generates named slot identifiers (e.g., `miden::component::miden_bank_account::initialized`) used in tests to reference specific slots. The compiler auto-assigns slot numbers based on field order. +The `description` attribute generates named slot identifiers (e.g., `miden_bank_account::bank::initialized`) used in tests to reference specific slots. The naming convention is `{package_name}::{component_struct}::{field_name}`. The compiler auto-assigns slot numbers based on field order. ## Step 2: Implement Component Methods @@ -160,31 +160,31 @@ Now let's add methods to our Bank. The `#[component]` attribute is also used on impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - // Read current value from storage - let current: Word = self.initialized.read(); + // Get current value from storage + let current: Word = self.initialized.get(); // Check not already initialized assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); // Set initialized flag to 1 let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } /// Check that the bank is initialized. fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -249,27 +249,26 @@ async fn test_bank_account_storage() -> anyhow::Result<()> { )?); // Create named storage slots matching the contract's storage layout - // The naming convention is: miden::component::{package_name_underscored}::{field_name} + // The naming convention is: {package_name}::{component_struct}::{field_name} let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot.clone(), Word::default()), - StorageSlot::with_map( - balances_slot.clone(), - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // ========================================================================= // VERIFY: Check initial storage state @@ -285,7 +284,7 @@ async fn test_bank_account_storage() -> anyhow::Result<()> { println!("Bank account created successfully!"); println!(" Account ID: {:?}", bank_account.id()); - println!(" Initialized flag: {:?}", initialized_value[0].as_int()); + println!(" Initialized flag: {:?}", initialized_value[0].as_canonical_u64()); // ========================================================================= // VERIFY: Storage slots are correctly configured @@ -365,43 +364,43 @@ struct Bank { /// Tracks whether the bank has been initialized (deposits enabled). /// Word layout: [is_initialized (0 or 1), 0, 0, 0] #[storage(description = "initialized")] - initialized: Value, + initialized: StorageValue, /// Maps depositor AccountId -> balance (as Felt) /// Key: [prefix, suffix, asset_prefix, asset_suffix] #[storage(description = "balances")] - balances: StorageMap, + balances: StorageMap, } #[component] impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - // Read current value from storage - let current: Word = self.initialized.read(); + // Get current value from storage + let current: Word = self.initialized.get(); // Check not already initialized assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); // Set initialized flag to 1 let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } /// Check that the bank is initialized. fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -413,8 +412,8 @@ impl Bank { ## Key Takeaways 1. **`#[component]`** marks structs and impl blocks as Miden account components -2. **`Value`** stores a single Word, read with `.read()`, write with `.write()` -3. **`StorageMap`** stores key-value pairs, access with `.get()` and `.set()` +2. **`StorageValue`** stores a single Word, read with `.get()`, write with `.set()` +3. **`StorageMap`** stores key-value pairs, access with `.get()` and `.set()` 4. **Storage slots** are identified by name (auto-assigned by compiler), each holds 4 Felts (32 bytes) 5. **Public methods** are callable by other contracts via generated bindings diff --git a/docs/src/miden-bank/02-constants-constraints.md b/docs/src/miden-bank/02-constants-constraints.md index 06ec58ec..c82b65ed 100644 --- a/docs/src/miden-bank/02-constants-constraints.md +++ b/docs/src/miden-bank/02-constants-constraints.md @@ -14,7 +14,7 @@ By the end of this section, you will have: - Defined constants for business rules - Used `assert!()` for transaction validation -- Learned safe Felt comparison with `.as_u64()` +- Learned safe Felt comparison with `.as_canonical_u64()` - Added a deposit method skeleton with validation - **Verified constraints work** by testing that invalid operations fail @@ -62,15 +62,15 @@ The `assert!()` macro validates conditions during transaction execution: ```rust title="contracts/bank-account/src/lib.rs" pub fn initialize(&mut self) { // Check not already initialized - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); // Set initialized flag to 1 let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } ``` @@ -101,12 +101,12 @@ if deposit_amount > felt!(1_000_000) { ```rust // CORRECT - convert to u64 first -if deposit_amount.as_u64() > MAX_DEPOSIT_AMOUNT { +if deposit_amount.as_canonical_u64() > MAX_DEPOSIT_AMOUNT { // This works correctly } ``` -The `.as_u64()` method extracts the underlying 64-bit integer from a Felt, allowing standard Rust comparisons. +The `.as_canonical_u64()` method extracts the underlying 64-bit integer from a Felt, allowing standard Rust comparisons. ## Step 1: Add the Constant and Deposit Method @@ -122,27 +122,27 @@ const MAX_DEPOSIT_AMOUNT: u64 = 1_000_000; impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } /// Check that the bank is initialized. fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -156,13 +156,13 @@ impl Bank { self.require_initialized(); // Extract the fungible amount from the asset - let deposit_amount = deposit_asset.inner[0]; + let deposit_amount = deposit_asset.value[0]; // ======================================================================== // CONSTRAINT: Maximum deposit amount check // ======================================================================== assert!( - deposit_amount.as_u64() <= MAX_DEPOSIT_AMOUNT, + deposit_amount.as_canonical_u64() <= MAX_DEPOSIT_AMOUNT, "Deposit amount exceeds maximum allowed" ); @@ -178,9 +178,9 @@ We use a helper method to check initialization state: ```rust fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -256,31 +256,30 @@ async fn test_constraints_are_defined() -> anyhow::Result<()> { // Create named storage slots let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); // Create an uninitialized bank account + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot.clone(), Word::default()), - StorageSlot::with_map( - balances_slot, - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // Verify the bank starts uninitialized let initialized = bank_account.storage().get_item(&initialized_slot)?; assert_eq!( - initialized[0].as_int(), + initialized[0].as_canonical_u64(), 0, "Bank should start uninitialized" ); @@ -288,7 +287,7 @@ async fn test_constraints_are_defined() -> anyhow::Result<()> { println!("Bank account created with constraints!"); println!(" - MAX_DEPOSIT_AMOUNT: 1,000,000"); println!(" - require_initialized() guard in place"); - println!(" - Initialization status: {}", initialized[0].as_int()); + println!(" - Initialization status: {}", initialized[0].as_canonical_u64()); println!("\nPart 2 constraints test passed!"); Ok(()) @@ -340,7 +339,7 @@ For now, the constraint logic is in place and we've verified the contract compil fn require_sufficient_balance(&self, depositor: AccountId, amount: Felt) { let balance = self.get_balance(depositor); assert!( - balance.as_u64() >= amount.as_u64(), + balance.as_canonical_u64() >= amount.as_canonical_u64(), "Insufficient balance" ); } @@ -354,9 +353,9 @@ This pattern is **mandatory** for any operation that subtracts from a balance. M ```rust fn require_not_paused(&self) { - let paused: Word = self.paused.read(); + let paused: Word = self.paused.get(); assert!( - paused[0].as_u64() == 0, + paused[0].as_canonical_u64() == 0, "Contract is paused" ); } @@ -385,37 +384,37 @@ const MAX_DEPOSIT_AMOUNT: u64 = 1_000_000; #[component] struct Bank { #[storage(description = "initialized")] - initialized: Value, + initialized: StorageValue, #[storage(description = "balances")] - balances: StorageMap, + balances: StorageMap, } #[component] impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } /// Check that the bank is initialized. fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -425,11 +424,11 @@ impl Bank { // CONSTRAINT: Bank must be initialized self.require_initialized(); - let deposit_amount = deposit_asset.inner[0]; + let deposit_amount = deposit_asset.value[0]; // CONSTRAINT: Maximum deposit amount check assert!( - deposit_amount.as_u64() <= MAX_DEPOSIT_AMOUNT, + deposit_amount.as_canonical_u64() <= MAX_DEPOSIT_AMOUNT, "Deposit amount exceeds maximum allowed" ); @@ -444,7 +443,7 @@ impl Bank { 1. **Constants** define immutable business rules at compile time 2. **`assert!()`** enforces constraints - failures reject the transaction -3. **Always use `.as_u64()`** for Felt comparisons, never direct operators +3. **Always use `.as_canonical_u64()`** for Felt comparisons, never direct operators 4. **Helper methods** like `require_initialized()` centralize validation logic 5. **Failed assertions** mean no valid proof can be generated diff --git a/docs/src/miden-bank/03-asset-management.md b/docs/src/miden-bank/03-asset-management.md index 6c8c2ffe..f49857b7 100644 --- a/docs/src/miden-bank/03-asset-management.md +++ b/docs/src/miden-bank/03-asset-management.md @@ -51,12 +51,12 @@ Asset Layout: [amount, 0, faucet_suffix, faucet_prefix] | 2 | `faucet_suffix` | Second part of the faucet account ID | | 3 | `faucet_prefix` | First part of the faucet account ID | -Access these fields through `asset.inner`: +Access amount through `asset.value` and faucet ID through `asset.key`: ```rust -let amount = deposit_asset.inner[0]; // The token amount -let faucet_suffix = deposit_asset.inner[2]; // Faucet ID suffix -let faucet_prefix = deposit_asset.inner[3]; // Faucet ID prefix +let amount = deposit_asset.value[0]; // The token amount +let faucet_suffix = deposit_asset.key[2]; // Faucet ID suffix +let faucet_prefix = deposit_asset.key[3]; // Faucet ID prefix ``` ## Receiving Assets with add_asset() @@ -90,14 +90,14 @@ pub fn deposit(&mut self, depositor: AccountId, deposit_asset: Asset) { // ======================================================================== self.require_initialized(); - // Extract the fungible amount from the asset - let deposit_amount = deposit_asset.inner[0]; + // Extract the fungible amount from the asset value word + let deposit_amount = deposit_asset.value[0]; // ======================================================================== // CONSTRAINT: Maximum deposit amount check // ======================================================================== assert!( - deposit_amount.as_u64() <= MAX_DEPOSIT_AMOUNT, + deposit_amount.as_canonical_u64() <= MAX_DEPOSIT_AMOUNT, "Deposit amount exceeds maximum allowed" ); @@ -109,12 +109,12 @@ pub fn deposit(&mut self, depositor: AccountId, deposit_asset: Asset) { let key = Word::from([ depositor.prefix, depositor.suffix, - deposit_asset.inner[3], // asset prefix (faucet) - deposit_asset.inner[2], // asset suffix (faucet) + deposit_asset.key[3], // faucet_prefix + deposit_asset.key[2], // faucet_suffix ]); // Update balance: current + deposit_amount - let current_balance: Felt = self.balances.get(&key); + let current_balance: Felt = self.balances.get(key); let new_balance = current_balance + deposit_amount; self.balances.set(key, new_balance); @@ -131,10 +131,10 @@ We construct a composite key for balance tracking: ```rust let key = Word::from([ - depositor.prefix, // Who deposited + depositor.prefix, // Who deposited depositor.suffix, - deposit_asset.inner[3], // Which asset type (faucet ID prefix) - deposit_asset.inner[2], // Which asset type (faucet ID suffix) + deposit_asset.key[3], // Which asset type (faucet ID prefix) + deposit_asset.key[2], // Which asset type (faucet ID suffix) ]); ``` @@ -162,7 +162,7 @@ let new_balance = current_balance - withdraw_amount; // CORRECT - Always validate first assert!( - current_balance.as_u64() >= withdraw_amount.as_u64(), + current_balance.as_canonical_u64() >= withdraw_amount.as_canonical_u64(), "Withdrawal amount exceeds available balance" ); let new_balance = current_balance - withdraw_amount; @@ -189,15 +189,15 @@ pub fn withdraw( // ======================================================================== self.require_initialized(); - // Extract the fungible amount from the asset - let withdraw_amount = withdraw_asset.inner[0]; + // Extract the fungible amount from the asset value word + let withdraw_amount = withdraw_asset.value[0]; // Create key from depositor's AccountId and asset faucet ID let key = Word::from([ depositor.prefix, depositor.suffix, - withdraw_asset.inner[3], - withdraw_asset.inner[2], + withdraw_asset.key[3], // faucet_prefix + withdraw_asset.key[2], // faucet_suffix ]); // ======================================================================== @@ -206,9 +206,9 @@ pub fn withdraw( // Get current balance and validate sufficient funds exist. // This check is critical: Felt arithmetic is modular, so subtracting // more than the balance would silently wrap to a large positive number. - let current_balance: Felt = self.balances.get(&key); + let current_balance: Felt = self.balances.get(key); assert!( - current_balance.as_u64() >= withdraw_amount.as_u64(), + current_balance.as_canonical_u64() >= withdraw_amount.as_canonical_u64(), "Withdrawal amount exceeds available balance" ); @@ -261,8 +261,9 @@ use integration::helpers::{ }; use miden_client::account::{StorageMap, StorageSlot, StorageSlotName}; use miden_client::asset::{Asset, FungibleAsset}; +use miden_client::auth::AuthSchemeId; use miden_client::note::NoteAssets; -use miden_client::transaction::{OutputNote, TransactionScript}; +use miden_client::transaction::{RawOutputNote, TransactionScript}; use miden_client::{Felt, Word}; use miden_testing::{Auth, MockChain}; use std::{path::Path, sync::Arc}; @@ -275,10 +276,10 @@ async fn test_deposit_updates_balance() -> anyhow::Result<()> { let mut builder = MockChain::builder(); // Create a faucet for test tokens - let faucet = builder.add_existing_basic_faucet(Auth::BasicAuth, "TEST", 10_000_000, Some(10))?; + let faucet = builder.add_existing_basic_faucet(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, "TEST", 10_000_000, Some(10))?; // Create sender wallet with tokens - let sender = builder.add_existing_wallet_with_assets(Auth::BasicAuth, [FungibleAsset::new(faucet.id(), 1000)?.into()])?; + let sender = builder.add_existing_wallet_with_assets(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, [FungibleAsset::new(faucet.id(), 1000)?.into()])?; // Build contracts let bank_package = Arc::new(build_project_in_dir( @@ -298,25 +299,24 @@ async fn test_deposit_updates_balance() -> anyhow::Result<()> { // Create the bank account with storage slots let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot.clone(), Word::default()), - StorageSlot::with_map( - balances_slot.clone(), - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let mut bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // Add to mock chain builder.add_account(bank_account.clone())?; @@ -338,7 +338,7 @@ async fn test_deposit_updates_balance() -> anyhow::Result<()> { )?; // Add note to builder before building - builder.add_output_note(OutputNote::Full(deposit_note.clone())); + builder.add_output_note(RawOutputNote::Full(deposit_note.clone())); let mut mock_chain = builder.build()?; @@ -361,7 +361,7 @@ async fn test_deposit_updates_balance() -> anyhow::Result<()> { // Verify initialization let initialized = bank_account.storage().get_item(&initialized_slot)?; assert_eq!( - initialized[0].as_int(), + initialized[0].as_canonical_u64(), 1, "Bank should be initialized" ); @@ -396,7 +396,7 @@ async fn test_deposit_updates_balance() -> anyhow::Result<()> { let balance = bank_account.storage().get_map_item(&balances_slot, depositor_key)?; // Balance is stored as a single Felt in the last position of the Word - let balance_value = balance[3].as_int(); + let balance_value = balance[3].as_canonical_u64(); println!("Depositor balance: {}", balance_value); assert_eq!( @@ -493,37 +493,37 @@ const MAX_DEPOSIT_AMOUNT: u64 = 1_000_000; #[component] struct Bank { #[storage(description = "initialized")] - initialized: Value, + initialized: StorageValue, #[storage(description = "balances")] - balances: StorageMap, + balances: StorageMap, } #[component] impl Bank { /// Initialize the bank account, enabling deposits. pub fn initialize(&mut self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 0, + current[0].as_canonical_u64() == 0, "Bank already initialized" ); let initialized_word = Word::from([felt!(1), felt!(0), felt!(0), felt!(0)]); - self.initialized.write(initialized_word); + self.initialized.set(initialized_word); } /// Get the balance for a depositor. pub fn get_balance(&self, depositor: AccountId) -> Felt { let key = Word::from([depositor.prefix, depositor.suffix, felt!(0), felt!(0)]); - self.balances.get(&key) + self.balances.get(key) } /// Check that the bank is initialized. fn require_initialized(&self) { - let current: Word = self.initialized.read(); + let current: Word = self.initialized.get(); assert!( - current[0].as_u64() == 1, + current[0].as_canonical_u64() == 1, "Bank not initialized - deposits not enabled" ); } @@ -532,21 +532,21 @@ impl Bank { pub fn deposit(&mut self, depositor: AccountId, deposit_asset: Asset) { self.require_initialized(); - let deposit_amount = deposit_asset.inner[0]; + let deposit_amount = deposit_asset.value[0]; assert!( - deposit_amount.as_u64() <= MAX_DEPOSIT_AMOUNT, + deposit_amount.as_canonical_u64() <= MAX_DEPOSIT_AMOUNT, "Deposit amount exceeds maximum allowed" ); let key = Word::from([ depositor.prefix, depositor.suffix, - deposit_asset.inner[3], - deposit_asset.inner[2], + deposit_asset.key[3], // faucet_prefix + deposit_asset.key[2], // faucet_suffix ]); - let current_balance: Felt = self.balances.get(&key); + let current_balance: Felt = self.balances.get(key); let new_balance = current_balance + deposit_amount; self.balances.set(key, new_balance); @@ -564,19 +564,19 @@ impl Bank { ) { self.require_initialized(); - let withdraw_amount = withdraw_asset.inner[0]; + let withdraw_amount = withdraw_asset.value[0]; let key = Word::from([ depositor.prefix, depositor.suffix, - withdraw_asset.inner[3], - withdraw_asset.inner[2], + withdraw_asset.key[3], // faucet_prefix + withdraw_asset.key[2], // faucet_suffix ]); // CRITICAL: Validate balance BEFORE subtraction - let current_balance: Felt = self.balances.get(&key); + let current_balance: Felt = self.balances.get(key); assert!( - current_balance.as_u64() >= withdraw_amount.as_u64(), + current_balance.as_canonical_u64() >= withdraw_amount.as_canonical_u64(), "Withdrawal amount exceeds available balance" ); @@ -604,7 +604,7 @@ impl Bank { ## Key Takeaways -1. **Asset layout**: `[amount, 0, faucet_suffix, faucet_prefix]` +1. **Asset layout**: `value[0]` = amount; `key[2]` = faucet_suffix; `key[3]` = faucet_prefix 2. **`native_account::add_asset()`** adds assets to the vault 3. **`native_account::remove_asset()`** removes assets from the vault (Part 7) 4. **Balance tracking** is application-level logic using `StorageMap` diff --git a/docs/src/miden-bank/04-note-scripts.md b/docs/src/miden-bank/04-note-scripts.md index 441591b0..424d3569 100644 --- a/docs/src/miden-bank/04-note-scripts.md +++ b/docs/src/miden-bank/04-note-scripts.md @@ -77,7 +77,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -miden = { version = "0.10" } +miden = { version = "0.12" } [package.metadata.component] package = "miden:deposit-note" @@ -172,14 +172,14 @@ for asset in assets { Returns an iterator over all assets attached to the note. -### get_inputs() - Note Parameters +### get_storage() - Note Parameters ```rust -let inputs = active_note::get_inputs(); -let first_input = inputs[0]; +let storage = active_note::get_storage(); +let first_item = storage[0]; ``` -Returns a vector of `Felt` values passed when the note was created. We'll use inputs in the withdraw request note (Part 7). +Returns a slice of `Felt` values passed when the note was created. We'll use storage items in the withdraw request note (Part 7). ## Step 4: Update the Workspace @@ -270,9 +270,10 @@ use integration::helpers::{ create_testing_note_from_package, AccountCreationConfig, NoteCreationConfig, }; use miden_client::account::{StorageMap, StorageSlot, StorageSlotName}; -use miden_client::note::NoteAssets; -use miden_client::transaction::{OutputNote, TransactionScript}; use miden_client::asset::{Asset, FungibleAsset}; +use miden_client::auth::AuthSchemeId; +use miden_client::note::NoteAssets; +use miden_client::transaction::{RawOutputNote, TransactionScript}; use miden_client::{Felt, Word}; use miden_testing::{Auth, MockChain}; use std::{path::Path, sync::Arc}; @@ -285,10 +286,10 @@ async fn test_deposit_note_credits_depositor() -> anyhow::Result<()> { let mut builder = MockChain::builder(); // Create a faucet for test tokens - let faucet = builder.add_existing_basic_faucet(Auth::BasicAuth, "TEST", 10_000_000, Some(10))?; + let faucet = builder.add_existing_basic_faucet(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, "TEST", 10_000_000, Some(10))?; // Create sender (depositor) wallet - let sender = builder.add_existing_wallet_with_assets(Auth::BasicAuth, [FungibleAsset::new(faucet.id(), 1000)?.into()])?; + let sender = builder.add_existing_wallet_with_assets(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, [FungibleAsset::new(faucet.id(), 1000)?.into()])?; // Build all contracts let bank_package = Arc::new(build_project_in_dir( @@ -308,25 +309,24 @@ async fn test_deposit_note_credits_depositor() -> anyhow::Result<()> { // Create bank account let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot, Word::default()), - StorageSlot::with_map( - balances_slot.clone(), - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let mut bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; builder.add_account(bank_account.clone())?; @@ -344,7 +344,7 @@ async fn test_deposit_note_credits_depositor() -> anyhow::Result<()> { }, )?; - builder.add_output_note(OutputNote::Full(deposit_note.clone())); + builder.add_output_note(RawOutputNote::Full(deposit_note.clone())); let mut mock_chain = builder.build()?; // ========================================================================= @@ -390,7 +390,7 @@ async fn test_deposit_note_credits_depositor() -> anyhow::Result<()> { ]); let balance = bank_account.storage().get_map_item(&balances_slot, depositor_key)?; - let balance_value = balance[3].as_int(); + let balance_value = balance[3].as_canonical_u64(); println!("Step 3: Verified balance = {}", balance_value); @@ -449,11 +449,12 @@ For withdrawals, we'll use note inputs to pass parameters. Here's a preview of t ```rust title="contracts/withdraw-request-note/src/lib.rs (preview)" /// Withdraw Request Note Script /// -/// # Note Inputs (10 Felts) -/// [0-3]: withdraw asset (amount, 0, faucet_suffix, faucet_prefix) +/// # Note Storage (14 Felts) +/// [0-3]: withdraw asset encoded as [amount, 0, faucet_suffix, faucet_prefix] /// [4-7]: serial_num (random/unique per note) /// [8]: tag (P2ID note tag for routing) /// [9]: note_type (1 = Public, 2 = Private) +/// [10-13]: P2ID script_root (MAST root of the P2ID note script, Poseidon2-hashed) #[note] struct WithdrawRequestNote; @@ -462,19 +463,23 @@ impl WithdrawRequestNote { #[note_script] fn run(self, _arg: Word) { let depositor = active_note::get_sender(); - let inputs = active_note::get_inputs(); + let storage = active_note::get_storage(); - // Parse parameters from inputs - let withdraw_asset = Asset::new(Word::from([ - inputs[0], inputs[1], inputs[2], inputs[3] - ])); + // Parse parameters from storage + let withdraw_asset = Asset::new( + Word::from([felt!(0), felt!(0), storage[2], storage[3]]), + Word::from([storage[0], felt!(0), felt!(0), felt!(0)]), + ); let serial_num = Word::from([ - inputs[4], inputs[5], inputs[6], inputs[7] + storage[4], storage[5], storage[6], storage[7] ]); - let tag = inputs[8]; - let note_type = inputs[9]; + let tag = storage[8]; + let note_type = storage[9]; + + // Note: P2ID script root (storage[10..13]) is read by the bank account + // directly from the active note's storage inside bank_account::withdraw. bank_account::withdraw(depositor, withdraw_asset, serial_num, tag, note_type); } @@ -523,7 +528,7 @@ impl DepositNote { 1. **`#[note]`** marks the struct and impl block, with **`#[note_script]`** on the entry point method `fn run(self, _arg: Word)` 2. **`active_note::get_sender()`** returns who created the note 3. **`active_note::get_assets()`** returns assets attached to the note -4. **`active_note::get_inputs()`** returns parameterized data +4. **`active_note::get_storage()`** returns parameterized data 5. **Note scripts execute once** when consumed - no persistent state 6. **Build order matters** - account components first, then note scripts diff --git a/docs/src/miden-bank/06-transaction-scripts.md b/docs/src/miden-bank/06-transaction-scripts.md index 7e67d774..e8dd1364 100644 --- a/docs/src/miden-bank/06-transaction-scripts.md +++ b/docs/src/miden-bank/06-transaction-scripts.md @@ -81,7 +81,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -miden = { version = "0.10" } +miden = { version = "0.12" } [package.metadata.component] package = "miden:init-tx-script" @@ -315,30 +315,29 @@ async fn test_init_tx_script_enables_deposits() -> anyhow::Result<()> { // Create uninitialized bank account with named storage slots let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot.clone(), Word::default()), - StorageSlot::with_map( - balances_slot, - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let mut bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // Verify bank is NOT initialized let initial_storage = bank_account.storage().get_item(&initialized_slot)?; assert_eq!( - initial_storage[0].as_int(), + initial_storage[0].as_canonical_u64(), 0, "Bank should start uninitialized" ); @@ -367,7 +366,7 @@ async fn test_init_tx_script_enables_deposits() -> anyhow::Result<()> { // Verify bank IS now initialized let final_storage = bank_account.storage().get_item(&initialized_slot)?; assert_eq!( - final_storage[0].as_int(), + final_storage[0].as_canonical_u64(), 1, "Bank should be initialized after tx script" ); @@ -460,7 +459,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -miden = { version = "0.10" } +miden = { version = "0.12" } [package.metadata.component] package = "miden:init-tx-script" diff --git a/docs/src/miden-bank/07-output-notes.md b/docs/src/miden-bank/07-output-notes.md index 2838721a..3f7ffaab 100644 --- a/docs/src/miden-bank/07-output-notes.md +++ b/docs/src/miden-bank/07-output-notes.md @@ -102,23 +102,23 @@ impl Bank { // Ensure the bank is initialized before processing withdrawals self.require_initialized(); - // Extract the fungible amount from the asset - let withdraw_amount = withdraw_asset.inner[0]; + // Extract the fungible amount from the asset value word + let withdraw_amount = withdraw_asset.value[0]; // Create key from depositor's AccountId and asset faucet ID let key = Word::from([ depositor.prefix, depositor.suffix, - withdraw_asset.inner[3], // asset prefix (faucet) - withdraw_asset.inner[2], // asset suffix (faucet) + withdraw_asset.key[3], // faucet_prefix + withdraw_asset.key[2], // faucet_suffix ]); // Get current balance and validate sufficient funds exist. // This check is critical: Felt arithmetic is modular, so subtracting // more than the balance would silently wrap to a large positive number. - let current_balance: Felt = self.balances.get(&key); + let current_balance: Felt = self.balances.get(key); assert!( - current_balance.as_u64() >= withdraw_amount.as_u64(), + current_balance.as_canonical_u64() >= withdraw_amount.as_canonical_u64(), "Withdrawal amount exceeds available balance" ); @@ -126,8 +126,13 @@ impl Bank { let new_balance = current_balance - withdraw_amount; self.balances.set(key, new_balance); + // Read the P2ID script root from the withdraw-request note's storage (items 10-13). + // This avoids hardcoding a version-specific MAST root constant. + let storage = active_note::get_storage(); + let script_root = Word::from([storage[10], storage[11], storage[12], storage[13]]); + // Create a P2ID note to send the requested asset back to the depositor - self.create_p2id_note(serial_num, &withdraw_asset, depositor, tag, note_type); + self.create_p2id_note(serial_num, &withdraw_asset, depositor, tag, note_type, script_root); } } ``` @@ -136,33 +141,16 @@ impl Bank { Always validate `current_balance >= withdraw_amount` BEFORE subtraction. Miden uses modular field arithmetic - subtracting a larger value silently wraps to a massive positive number! ::: -## Step 2: Add the P2ID Note Root +## Step 2: How the P2ID Script Root is Supplied -The P2ID note uses a standard script from miden-standards. Add this helper function: +Instead of hardcoding a version-specific MAST root constant in the bank contract, the P2ID script root is passed through the withdraw-request note's storage (items 10-13). The `withdraw()` method reads it directly from the active note: -```rust title="contracts/bank-account/src/lib.rs" -#[component] -impl Bank { - // ... other methods ... - - /// Returns the P2ID note script root digest. - /// - /// This is a constant value derived from the standard P2ID note script in miden-standards. - /// The digest is the MAST root of the compiled P2ID note script. - fn p2id_note_root() -> Digest { - Digest::from_word(Word::new([ - Felt::from_u64_unchecked(13362761878458161062), - Felt::from_u64_unchecked(15090726097241769395), - Felt::from_u64_unchecked(444910447169617901), - Felt::from_u64_unchecked(3558201871398422326), - ])) - } -} +```rust +let storage = active_note::get_storage(); +let script_root = Word::from([storage[10], storage[11], storage[12], storage[13]]); ``` -:::warning Version-Specific -This digest is specific to miden-standards version. If the P2ID script changes in a future version, this digest must be updated. -::: +This design keeps the bank contract version-agnostic: callers embed the P2ID script root they want to use into the note storage when they create the withdraw-request note. The test uses `P2idNote::script_root()` from the `miden_client` crate to obtain the correct value at test time. ## Step 3: Implement create_p2id_note @@ -181,6 +169,7 @@ impl Bank { /// * `recipient_id` - The AccountId that can consume this note /// * `tag` - The note tag (passed by caller to allow proper P2ID routing) /// * `note_type` - Note type as Felt: 1 = Public, 2 = Private + /// * `script_root` - The P2ID note script MAST root (Poseidon2-hashed) fn create_p2id_note( &mut self, serial_num: Word, @@ -188,6 +177,7 @@ impl Bank { recipient_id: AccountId, tag: Felt, note_type: Felt, + script_root: Word, ) { // Convert the passed tag Felt to a Tag // The caller is responsible for computing the proper P2ID tag @@ -198,16 +188,13 @@ impl Bank { // 1 = Public (stored on-chain), 2 = Private (off-chain) let note_type = NoteType::from(note_type); - // Get the P2ID note script root digest - let script_root = Self::p2id_note_root(); - // Compute the recipient hash from: // - serial_num: unique identifier for this note instance // - script_root: the P2ID note script's MAST root - // - inputs: the target account ID + // - storage: the target account ID // // The P2ID script expects inputs as [suffix, prefix] - let recipient = Recipient::compute( + let recipient = note::build_recipient( serial_num, script_root, vec![ @@ -228,13 +215,13 @@ impl Bank { } ``` -### Understanding Recipient::compute() +### Understanding note::build_recipient() -| Parameter | Description | -| ------------- | ----------------------------------------- | -| `serial_num` | Unique 4-Felt value preventing note reuse | -| `script_root` | The P2ID script's MAST root digest | -| `inputs` | Script inputs (account ID for P2ID) | +| Parameter | Description | +| ------------- | ------------------------------------------ | +| `serial_num` | Unique 4-Felt value preventing note reuse | +| `script_root` | The P2ID script's MAST root digest | +| `storage` | Script storage items (account ID for P2ID) | :::warning Array Ordering Note the order: `suffix` comes before `prefix`. This is the opposite of how `AccountId` fields are typically accessed. See [Common Pitfalls](https://docs.miden.xyz/builder/tutorials/rust-compiler/pitfalls#array-ordering-rustmasm-reversal) for details. @@ -268,7 +255,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -miden = { version = "0.10" } +miden = { version = "0.12" } [package.metadata.component] package = "miden:withdraw-request-note" @@ -323,16 +310,17 @@ use crate::bindings::miden::bank_account::bank_account; /// # Flow /// 1. Note is created by a depositor specifying the withdrawal details /// 2. Bank account consumes this note -/// 3. Note script reads the sender (depositor) and inputs +/// 3. Note script reads the sender (depositor) and storage items /// 4. Calls `bank_account::withdraw(depositor, asset, serial_num, tag, note_type)` /// 5. Bank updates the depositor's balance -/// 6. Bank creates a P2ID note with the specified parameters to send assets back +/// 6. Bank reads P2ID script root from storage[10-13] and creates a P2ID output note /// -/// # Note Inputs (10 Felts) -/// [0-3]: withdraw asset (amount, 0, faucet_suffix, faucet_prefix) +/// # Note Storage (14 Felts) +/// [0-3]: withdraw asset encoded as [amount, 0, faucet_suffix, faucet_prefix] /// [4-7]: serial_num (random/unique per note) /// [8]: tag (P2ID note tag for routing) /// [9]: note_type (1 = Public, 2 = Private) +/// [10-13]: P2ID script_root (MAST root of the P2ID note script, Poseidon2-hashed) #[note] struct WithdrawRequestNote; @@ -343,20 +331,26 @@ impl WithdrawRequestNote { // The depositor is whoever created/sent this note let depositor = active_note::get_sender(); - // Get the inputs - let inputs = active_note::get_inputs(); + // Get the storage items + let storage = active_note::get_storage(); - // Asset: [amount, 0, faucet_suffix, faucet_prefix] - let withdraw_asset = Asset::new(Word::from([inputs[0], inputs[1], inputs[2], inputs[3]])); + // Asset: reconstruct from [amount, 0, faucet_suffix, faucet_prefix] encoding + let withdraw_asset = Asset::new( + Word::from([felt!(0), felt!(0), storage[2], storage[3]]), + Word::from([storage[0], felt!(0), felt!(0), felt!(0)]), + ); // Serial number: full 4 Felts (random/unique per note) - let serial_num = Word::from([inputs[4], inputs[5], inputs[6], inputs[7]]); + let serial_num = Word::from([storage[4], storage[5], storage[6], storage[7]]); // Tag: single Felt for P2ID note routing - let tag = inputs[8]; + let tag = storage[8]; // Note type: 1 = Public, 2 = Private - let note_type = inputs[9]; + let note_type = storage[9]; + + // Note: P2ID script root (storage[10..13]) is read by the bank account + // directly from the active note's storage inside bank_account::withdraw. // Call the bank account to withdraw the assets bank_account::withdraw(depositor, withdraw_asset, serial_num, tag, note_type); @@ -364,12 +358,12 @@ impl WithdrawRequestNote { } ``` -### Note Input Layout +### Note Storage Layout -The withdraw-request-note expects 10 Felt inputs: +The withdraw-request-note uses 14 Felt storage items: ```text -Note Inputs (10 Felts): +Note Storage (14 Felts): β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Index β”‚ Value β”‚ Description β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ @@ -380,6 +374,7 @@ Note Inputs (10 Felts): β”‚ 4-7 β”‚ serial_num β”‚ Unique ID for the output P2ID note (4 Felts) β”‚ β”‚ 8 β”‚ tag β”‚ Note routing tag for P2ID note β”‚ β”‚ 9 β”‚ note_type β”‚ 1 (Public) or 2 (Private) β”‚ +β”‚ 10-13 β”‚ script_root β”‚ P2ID script MAST root (Poseidon2-hashed, 4 Felts)β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` @@ -407,7 +402,7 @@ Let's test the complete withdraw flow. This test: 1. Creates a bank account and initializes it 2. Creates a deposit note and processes it -3. Creates a withdraw-request note with the 10-Felt input layout +3. Creates a withdraw-request note with the 14-Felt storage layout 4. Processes the withdrawal and verifies a P2ID output note is created ```rust title="integration/tests/part7_withdraw_test.rs" @@ -418,8 +413,9 @@ use integration::helpers::{ use miden_client::{ account::{StorageMap, StorageSlotName}, asset::{Asset, FungibleAsset}, - note::{build_p2id_recipient, Note, NoteAssets, NoteMetadata, NoteTag, NoteType}, - transaction::{OutputNote, TransactionScript}, + auth::AuthSchemeId, + note::{P2idNote, P2idNoteStorage, Note, NoteAssets, NoteMetadata, NoteTag, NoteType}, + transaction::{RawOutputNote, TransactionScript}, Felt, Word, }; use miden_testing::{Auth, MockChain}; @@ -436,9 +432,9 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { // Create faucet and sender (depositor) let faucet = - builder.add_existing_basic_faucet(Auth::BasicAuth, "TEST", deposit_amount, Some(10))?; + builder.add_existing_basic_faucet(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, "TEST", deposit_amount, Some(10))?; let sender = builder.add_existing_wallet_with_assets( - Auth::BasicAuth, + Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, [FungibleAsset::new(faucet.id(), deposit_amount)?.into()], )?; @@ -462,24 +458,23 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { // Create bank account with named storage slots let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - miden_client::account::StorageSlot::with_value(initialized_slot, Word::default()), - miden_client::account::StorageSlot::with_map( - balances_slot, - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let mut bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; // Create deposit note let fungible_asset = FungibleAsset::new(faucet.id(), deposit_amount)?; @@ -495,10 +490,10 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { // Add accounts and notes to builder builder.add_account(bank_account.clone())?; - builder.add_output_note(OutputNote::Full(deposit_note.clone())); + builder.add_output_note(RawOutputNote::Full(deposit_note.clone())); // ========================================================================= - // CRAFT WITHDRAW REQUEST NOTE (10-Felt input layout) + // CRAFT WITHDRAW REQUEST NOTE (14-Felt storage layout) // ========================================================================= let withdraw_amount = deposit_amount / 2; @@ -516,12 +511,16 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { let note_type_felt = Felt::new(1); // Public - // Note inputs: 10 Felts + // Get the P2ID script root (Poseidon2-hashed MAST root) + let p2id_script_root = P2idNote::script_root(); + + // Note storage: 14 Felts // [0-3]: withdraw asset (amount, 0, faucet_suffix, faucet_prefix) // [4-7]: serial_num // [8]: tag // [9]: note_type - let withdraw_request_note_inputs = vec![ + // [10-13]: P2ID script_root + let withdraw_request_note_storage = vec![ Felt::new(withdraw_amount), Felt::new(0), faucet.id().suffix(), @@ -532,18 +531,22 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { p2id_output_note_serial_num[3], p2id_tag_felt, note_type_felt, + p2id_script_root[0], + p2id_script_root[1], + p2id_script_root[2], + p2id_script_root[3], ]; let withdraw_request_note = create_testing_note_from_package( withdraw_request_note_package.clone(), sender.id(), NoteCreationConfig { - inputs: withdraw_request_note_inputs, + storage: withdraw_request_note_storage, ..Default::default() }, )?; - builder.add_output_note(OutputNote::Full(withdraw_request_note.clone())); + builder.add_output_note(RawOutputNote::Full(withdraw_request_note.clone())); // ========================================================================= // EXECUTE: Initialize, Deposit, Withdraw @@ -576,14 +579,11 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { println!("Step 2: Deposited {} tokens", deposit_amount); // Process withdraw with expected P2ID output note - let recipient = build_p2id_recipient(sender.id(), p2id_output_note_serial_num)?; + let recipient = P2idNoteStorage::new(sender.id()).into_recipient(p2id_output_note_serial_num); let p2id_output_note_asset = FungibleAsset::new(faucet.id(), withdraw_amount)?; let p2id_output_note_assets = NoteAssets::new(vec![p2id_output_note_asset.into()])?; - let p2id_output_note_metadata = NoteMetadata::new( - bank_account.id(), - NoteType::Public, - p2id_tag, - ); + let p2id_output_note_metadata = NoteMetadata::new(bank_account.id(), NoteType::Public) + .with_tag(p2id_tag); let p2id_output_note = Note::new( p2id_output_note_assets, p2id_output_note_metadata, @@ -592,7 +592,7 @@ async fn test_withdraw_creates_p2id_note() -> anyhow::Result<()> { let withdraw_tx_context = mock_chain .build_tx_context(bank_account.id(), &[withdraw_request_note.id()], &[])? - .extend_expected_output_notes(vec![OutputNote::Full(p2id_output_note)]) + .extend_expected_output_notes(vec![RawOutputNote::Full(p2id_output_note)]) .build()?; let executed_withdraw = withdraw_tx_context.execute().await?; bank_account.apply_delta(&executed_withdraw.account_delta())?; @@ -668,11 +668,12 @@ use crate::bindings::miden::bank_account::bank_account; /// When consumed by the Bank account, this note requests a withdrawal and /// the bank creates a P2ID note to send assets back to the depositor. /// -/// # Note Inputs (10 Felts) -/// [0-3]: withdraw asset (amount, 0, faucet_suffix, faucet_prefix) +/// # Note Storage (14 Felts) +/// [0-3]: withdraw asset encoded as [amount, 0, faucet_suffix, faucet_prefix] /// [4-7]: serial_num (random/unique per note) /// [8]: tag (P2ID note tag for routing) /// [9]: note_type (1 = Public, 2 = Private) +/// [10-13]: P2ID script_root (MAST root of the P2ID note script, Poseidon2-hashed) #[note] struct WithdrawRequestNote; @@ -683,20 +684,26 @@ impl WithdrawRequestNote { // The depositor is whoever created/sent this note let depositor = active_note::get_sender(); - // Get the inputs - let inputs = active_note::get_inputs(); + // Get the storage items + let storage = active_note::get_storage(); - // Asset: [amount, 0, faucet_suffix, faucet_prefix] - let withdraw_asset = Asset::new(Word::from([inputs[0], inputs[1], inputs[2], inputs[3]])); + // Asset: reconstruct from [amount, 0, faucet_suffix, faucet_prefix] encoding + let withdraw_asset = Asset::new( + Word::from([felt!(0), felt!(0), storage[2], storage[3]]), + Word::from([storage[0], felt!(0), felt!(0), felt!(0)]), + ); // Serial number: full 4 Felts (random/unique per note) - let serial_num = Word::from([inputs[4], inputs[5], inputs[6], inputs[7]]); + let serial_num = Word::from([storage[4], storage[5], storage[6], storage[7]]); // Tag: single Felt for P2ID note routing - let tag = inputs[8]; + let tag = storage[8]; // Note type: 1 = Public, 2 = Private - let note_type = inputs[9]; + let note_type = storage[9]; + + // Note: P2ID script root (storage[10..13]) is read by the bank account + // directly from the active note's storage inside bank_account::withdraw. // Call the bank account to withdraw the assets bank_account::withdraw(depositor, withdraw_asset, serial_num, tag, note_type); @@ -708,7 +715,7 @@ impl WithdrawRequestNote { ## Key Takeaways -1. **`Recipient::compute()`** creates a cryptographic commitment from serial number, script root, and inputs +1. **`note::build_recipient()`** creates a cryptographic commitment from serial number, script root, and storage items 2. **`output_note::create()`** creates the note with tag, note type, and recipient 3. **`output_note::add_asset()`** attaches assets to the created note 4. **P2ID pattern** uses a standard script with account ID as input diff --git a/docs/src/miden-bank/08-complete-flows.md b/docs/src/miden-bank/08-complete-flows.md index c7243312..2406a703 100644 --- a/docs/src/miden-bank/08-complete-flows.md +++ b/docs/src/miden-bank/08-complete-flows.md @@ -119,7 +119,7 @@ Now let's trace the withdrawal process: β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Note script executes: β”‚ β”‚ β”‚ β”‚ sender = get_sender() β”‚ β”‚ -β”‚ β”‚ inputs = get_inputs() β”‚ β”‚ +β”‚ β”‚ storage = get_storage() β”‚ β”‚ β”‚ β”‚ asset = Asset from inputs β”‚ β”‚ β”‚ β”‚ bank_account::withdraw(...) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ @@ -137,8 +137,8 @@ Now let's trace the withdrawal process: β”‚ β–Ό β”‚ β”‚ 4. P2ID NOTE CREATED (inside create_p2id_note) β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ script_root = p2id_note_root() β†’ MAST digest β”‚ β”‚ -β”‚ β”‚ recipient = Recipient::compute( β”‚ β”‚ +β”‚ β”‚ script_root = storage[10..13] β†’ MAST digest β”‚ β”‚ +β”‚ β”‚ recipient = note::build_recipient( β”‚ β”‚ β”‚ β”‚ serial_num, script_root, β”‚ β”‚ β”‚ β”‚ [user.suffix, user.prefix] β”‚ β”‚ β”‚ β”‚ ) β”‚ β”‚ @@ -173,10 +173,11 @@ use integration::helpers::{ use miden_client::{ account::{StorageMap, StorageSlot, StorageSlotName}, asset::{Asset, FungibleAsset}, - note::{build_p2id_recipient, Note, NoteAssets, NoteMetadata, NoteTag, NoteType}, - transaction::{OutputNote, TransactionScript}, + note::{P2idNote, P2idNoteStorage, Note, NoteAssets, NoteMetadata, NoteTag, NoteType}, + transaction::{RawOutputNote, TransactionScript}, Felt, Word, }; +use miden_client::auth::AuthSchemeId; use miden_testing::{Auth, MockChain}; use std::{path::Path, sync::Arc}; @@ -205,11 +206,11 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { // Create a faucet to mint test assets let faucet = - builder.add_existing_basic_faucet(Auth::BasicAuth, "TEST", deposit_amount, Some(10))?; + builder.add_existing_basic_faucet(Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, "TEST", deposit_amount, Some(10))?; // Create note sender account (the depositor) let sender = builder.add_existing_wallet_with_assets( - Auth::BasicAuth, + Auth::BasicAuth { auth_scheme: AuthSchemeId::Falcon512Poseidon2 }, [FungibleAsset::new(faucet.id(), deposit_amount)?.into()], )?; println!(" βœ“ Faucet and sender wallet created"); @@ -235,25 +236,24 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { // Create named storage slots let initialized_slot = - StorageSlotName::new("miden::component::miden_bank_account::initialized") + StorageSlotName::new("miden_bank_account::bank::initialized") .expect("Valid slot name"); let balances_slot = - StorageSlotName::new("miden::component::miden_bank_account::balances") + StorageSlotName::new("miden_bank_account::bank::balances") .expect("Valid slot name"); // Create bank account with storage slots + let mut init_storage_data = InitStorageData::default(); + init_storage_data.insert_value( + StorageValueName::from_slot_name(&initialized_slot), + Word::default(), + )?; let bank_cfg = AccountCreationConfig { - storage_slots: vec![ - StorageSlot::with_value(initialized_slot, Word::default()), - StorageSlot::with_map( - balances_slot.clone(), - StorageMap::with_entries([]).expect("Empty storage map"), - ), - ], + init_storage_data, ..Default::default() }; let mut bank_account = - create_testing_account_from_package(bank_package.clone(), bank_cfg).await?; + create_testing_account_from_package(bank_package.clone(), bank_cfg)?; println!(" βœ“ Bank account created: {:?}", bank_account.id()); // Create deposit note with assets @@ -281,12 +281,16 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { let note_type_felt = Felt::new(1); // Public - // Note inputs: 10 Felts + // Get the P2ID script root (Poseidon2-hashed MAST root) + let p2id_script_root = P2idNote::script_root(); + + // Note storage: 14 Felts // [0-3]: withdraw asset (amount, 0, faucet_suffix, faucet_prefix) // [4-7]: serial_num // [8]: tag // [9]: note_type - let withdraw_request_note_inputs = vec![ + // [10-13]: P2ID script_root + let withdraw_request_note_storage = vec![ Felt::new(withdraw_amount), Felt::new(0), faucet.id().suffix(), @@ -297,21 +301,25 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { p2id_output_note_serial_num[3], p2id_tag_felt, note_type_felt, + p2id_script_root[0], + p2id_script_root[1], + p2id_script_root[2], + p2id_script_root[3], ]; let withdraw_request_note = create_testing_note_from_package( withdraw_request_note_package.clone(), sender.id(), NoteCreationConfig { - inputs: withdraw_request_note_inputs, + storage: withdraw_request_note_storage, ..Default::default() }, )?; // Add to builder builder.add_account(bank_account.clone())?; - builder.add_output_note(OutputNote::Full(deposit_note.clone())); - builder.add_output_note(OutputNote::Full(withdraw_request_note.clone())); + builder.add_output_note(RawOutputNote::Full(deposit_note.clone())); + builder.add_output_note(RawOutputNote::Full(withdraw_request_note.clone())); let mut mock_chain = builder.build()?; println!(" βœ“ MockChain built"); @@ -361,7 +369,7 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { let balance_after_deposit = bank_account.storage().get_map_item(&balances_slot, depositor_key)?; println!( " βœ“ Bank processed deposit, balance: {} tokens", - balance_after_deposit[3].as_int() + balance_after_deposit[3].as_canonical_u64() ); // ═══════════════════════════════════════════════════════════════════ @@ -371,14 +379,11 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { println!(" Withdraw amount: {} tokens", withdraw_amount); // Build expected P2ID output note - let recipient = build_p2id_recipient(sender.id(), p2id_output_note_serial_num)?; + let recipient = P2idNoteStorage::new(sender.id()).into_recipient(p2id_output_note_serial_num); let p2id_output_note_asset = FungibleAsset::new(faucet.id(), withdraw_amount)?; let p2id_output_note_assets = NoteAssets::new(vec![p2id_output_note_asset.into()])?; - let p2id_output_note_metadata = NoteMetadata::new( - bank_account.id(), - NoteType::Public, - p2id_tag, - ); + let p2id_output_note_metadata = NoteMetadata::new(bank_account.id(), NoteType::Public) + .with_tag(p2id_tag); let p2id_output_note = Note::new( p2id_output_note_assets, p2id_output_note_metadata, @@ -387,7 +392,7 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { let withdraw_tx_context = mock_chain .build_tx_context(bank_account.id(), &[withdraw_request_note.id()], &[])? - .extend_expected_output_notes(vec![OutputNote::Full(p2id_output_note)]) + .extend_expected_output_notes(vec![RawOutputNote::Full(p2id_output_note)]) .build()?; let executed_withdraw = withdraw_tx_context.execute().await?; @@ -400,7 +405,7 @@ async fn test_complete_bank_flow() -> anyhow::Result<()> { // Verify final balance let final_balance = bank_account.storage().get_map_item(&balances_slot, depositor_key)?; - let final_balance_amount = final_balance[3].as_int(); + let final_balance_amount = final_balance[3].as_canonical_u64(); let expected_final = deposit_amount - withdraw_amount; println!(" βœ“ Final balance verified: {} tokens", final_balance_amount); @@ -501,16 +506,16 @@ Here's the complete picture of what you've built: | `withdraw-request-note` | Note Script | Requests withdrawals | | `init-tx-script` | Transaction Script | Initializes the bank | -| Storage Slot | Type | Content | -| ------------- | ------------ | ------------------- | -| `initialized` | `Value` | Initialization flag | -| `balances` | `StorageMap` | Depositor balances | +| Storage Slot | Type | Content | +| ------------- | ------------------------ | ------------------- | +| `initialized` | `StorageValue` | Initialization flag | +| `balances` | `StorageMap` | Depositor balances | | API | Purpose | | -------------------------------- | --------------------- | | `active_note::get_sender()` | Identify note creator | | `active_note::get_assets()` | Get attached assets | -| `active_note::get_inputs()` | Get note parameters | +| `active_note::get_storage()` | Get note parameters | | `native_account::add_asset()` | Receive into vault | | `native_account::remove_asset()` | Send from vault | | `output_note::create()` | Create output note | @@ -528,12 +533,10 @@ let new_balance = current_balance - withdraw_amount; // βœ… SAFE: Validate first assert!( - current_balance.as_u64() >= withdraw_amount.as_u64(), + current_balance.as_canonical_u64() >= withdraw_amount.as_canonical_u64(), "Insufficient balance" ); -let new_balance = Felt::from_u64_unchecked( - current_balance.as_u64() - withdraw_amount.as_u64() -); +let new_balance = current_balance - withdraw_amount; ``` ::: @@ -545,8 +548,8 @@ Never use `<`, `>` on Felt values directly. Always convert to u64 first: // ❌ BROKEN: Produces incorrect results if current_balance < withdraw_amount { ... } -// βœ… CORRECT: Use as_u64() -if current_balance.as_u64() < withdraw_amount.as_u64() { ... } +// βœ… CORRECT: Use as_canonical_u64() +if current_balance.as_canonical_u64() < withdraw_amount.as_canonical_u64() { ... } ``` ::: @@ -555,7 +558,7 @@ if current_balance.as_u64() < withdraw_amount.as_u64() { ... } You've completed the Miden Bank tutorial! You now understand: -- βœ… **Account components** with storage (`Value` and `StorageMap`) +- βœ… **Account components** with storage (`StorageValue` and `StorageMap`) - βœ… **Constants and constraints** for business rules - βœ… **Asset management** with vault operations - βœ… **Note scripts** for processing incoming notes diff --git a/docs/src/miden_node_setup.md b/docs/src/miden_node_setup.md index 7e7bf66e..731af74a 100644 --- a/docs/src/miden_node_setup.md +++ b/docs/src/miden_node_setup.md @@ -29,9 +29,12 @@ On **Ubuntu**, see the [node installation page](https://docs.miden.xyz/miden-nod Install the miden-node crate using this command: ```bash -cargo install miden-node --locked --version 0.13.0 +# Installs from GitHub (crates.io publication was not verified): +cargo install --locked --git https://github.com/0xMiden/miden-node --tag v0.14.6 miden-node ``` +Check the [miden-node releases](https://github.com/0xMiden/miden-node/releases) for the latest version compatible with your target network. + ### Step 2: Initializing the node To start the node, we first need to generate the genesis file. Create the genesis file using this command: diff --git a/docs/src/rust-client/counter_contract_tutorial.md b/docs/src/rust-client/counter_contract_tutorial.md index 04a8d150..866deb2b 100644 --- a/docs/src/rust-client/counter_contract_tutorial.md +++ b/docs/src/rust-client/counter_contract_tutorial.md @@ -37,9 +37,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -72,31 +72,30 @@ use miden_client::{ builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; use miden_client::{ account::{ - AccountBuilder, AccountComponent, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode, + AccountType, StorageSlot, StorageSlotName, }, Word, }; fn create_library( - assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); + let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), source_code, - source_manager.clone(), + source_manager, )?; - let library = assembler.clone().assemble_library([module])?; + let library = assembler.assemble_library([module])?; Ok(library) } @@ -270,9 +269,9 @@ let component_code = CodeBuilder::new() let counter_component = AccountComponent::new( component_code, vec![StorageSlot::with_value(counter_slot_name.clone(), Word::default())], + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), ) -.unwrap() -.with_supports_all_types(); +.unwrap(); // Init seed for the counter contract let mut seed = [0_u8; 32]; @@ -289,7 +288,7 @@ let counter_contract = AccountBuilder::new(seed) println!( "counter_contract commitment: {:?}", - counter_contract.commitment() + counter_contract.to_commitment() ); println!("counter_contract id: {:?}", counter_contract.id()); println!("counter_contract storage: {:?}", counter_contract.storage()); @@ -308,7 +307,7 @@ After the program executes, you should see the counter contract hash and contrac ```text [STEP 1] Creating counter contract. counter_contract commitment: RpoDigest([3700134472268167470, 14878091556015233722, 3335592073702485043, 16978997897830363420]) -counter_contract id: "mtst1qql030hpsp0yyqra494lcwazxsym7add" +counter_contract id: "" counter_contract storage: AccountStorage { slots: [Value([0, 0, 0, 0]), Value([0, 0, 0, 0])] } ``` @@ -329,9 +328,7 @@ let script_path = Path::new("../masm/scripts/counter_script.masm"); let script_code = fs::read_to_string(script_path).unwrap(); // Create a library from the counter contract code -let assembler = TransactionKernel::assembler(); let account_component_lib = create_library( - assembler.clone(), "external_contract::counter_contract", &counter_code, ) @@ -369,15 +366,11 @@ println!( client.sync_state().await.unwrap(); // Retrieve updated contract data to see the incremented counter -let account_record = client +let account = client .get_account(counter_contract.id()) .await .unwrap() .expect("counter contract not found"); -let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), -}; println!( "counter contract storage: {:?}", account.storage().get_item(&counter_slot_name) @@ -409,31 +402,30 @@ use miden_client::{ builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; use miden_client::{ account::{ - AccountBuilder, AccountComponent, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode, + AccountType, StorageSlot, StorageSlotName, }, Word, }; fn create_library( - assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); + let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), source_code, - source_manager.clone(), + source_manager, )?; - let library = assembler.clone().assemble_library([module])?; + let library = assembler.assemble_library([module])?; Ok(library) } @@ -479,9 +471,9 @@ async fn main() -> Result<(), ClientError> { let counter_component = AccountComponent::new( component_code, vec![StorageSlot::with_value(counter_slot_name.clone(), Word::default())], + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), ) - .unwrap() - .with_supports_all_types(); + .unwrap(); // Init seed for the counter contract let mut seed = [0_u8; 32]; @@ -498,7 +490,7 @@ async fn main() -> Result<(), ClientError> { println!( "counter_contract commitment: {:?}", - counter_contract.commitment() + counter_contract.to_commitment() ); println!("counter_contract id: {:?}", counter_contract.id()); println!("counter_contract storage: {:?}", counter_contract.storage()); @@ -515,9 +507,7 @@ async fn main() -> Result<(), ClientError> { let script_code = fs::read_to_string(script_path).unwrap(); // Create a library from the counter contract code - let assembler = TransactionKernel::assembler(); let account_component_lib = create_library( - assembler.clone(), "external_contract::counter_contract", &counter_code, ) @@ -555,15 +545,11 @@ async fn main() -> Result<(), ClientError> { client.sync_state().await.unwrap(); // Retrieve updated contract data to see the incremented counter - let account_record = client + let account = client .get_account(counter_contract.id()) .await .unwrap() .expect("counter contract not found"); - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), - }; println!( "counter contract storage: {:?}", account.storage().get_item(&counter_slot_name) @@ -581,7 +567,7 @@ Latest block: 374255 [STEP 1] Creating counter contract. one or more warnings were emitted counter_contract commitment: Word([3964727668949550262, 4265714847747507878, 5784293172192015964, 16803438753763367241]) -counter_contract id: "mtst1qre73e6qcrfevqqngx8wewvveacqqjh8p2a" +counter_contract id: "" counter_contract storage: AccountStorage { slots: [Value(Word([0, 0, 0, 0]))] } [STEP 2] Call Counter Contract With Script diff --git a/docs/src/rust-client/create_deploy_tutorial.md b/docs/src/rust-client/create_deploy_tutorial.md index 0ce42ea0..f355e862 100644 --- a/docs/src/rust-client/create_deploy_tutorial.md +++ b/docs/src/rust-client/create_deploy_tutorial.md @@ -48,9 +48,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -70,7 +70,7 @@ Before interacting with the Miden network, we must instantiate the client. In th Copy and paste the following code into your `src/main.rs` file. ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::sync::Arc; use tokio::time::Duration; @@ -84,9 +84,9 @@ use miden_client::{ auth::AuthSecretKey, builder::ClientBuilder, keystore::FilesystemKeyStore, - note::{create_p2id_note, NoteType}, + note::{NoteType, P2idNote}, rpc::{Endpoint, GrpcClient}, - transaction::{OutputNote, TransactionRequestBuilder}, + transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; @@ -161,13 +161,13 @@ println!("\n[STEP 1] Creating a new account for Alice"); let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); -let key_pair = AuthSecretKey::new_falcon512_rpo(); +let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the account let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -176,7 +176,8 @@ let alice_account = AccountBuilder::new(init_seed) client.add_account(&alice_account, false).await?; // Add the key pair to the keystore -keystore.add_key(&key_pair).unwrap(); +use miden_client::keystore::Keystore; +keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); let alice_account_id_bech32 = alice_account.id().to_bech32(NetworkId::Testnet); println!("Alice's account ID: {:?}", alice_account_id_bech32); @@ -206,13 +207,13 @@ let decimals = 8; let max_supply = Felt::new(1_000_000); // Generate key pair -let key_pair = AuthSecretKey::new_falcon512_rpo(); +let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the faucet account let faucet_account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) .build() .unwrap(); @@ -221,7 +222,8 @@ let faucet_account = AccountBuilder::new(init_seed) client.add_account(&faucet_account, false).await?; // Add the key pair to the keystore -keystore.add_key(&key_pair).unwrap(); +use miden_client::keystore::Keystore; +keystore.add_key(&key_pair, faucet_account.id()).await.unwrap(); let faucet_account_id_bech32 = faucet_account.id().to_bech32(NetworkId::Testnet); println!("Faucet account ID: {:?}", faucet_account_id_bech32); @@ -238,23 +240,23 @@ _When tokens are minted from this faucet, each token batch is represented as a " Your updated `main()` function in `src/main.rs` should look like this: ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::sync::Arc; use tokio::time::Duration; use miden_client::{ account::{ - component::{BasicFungibleFaucet, BasicWallet}, + component::{AuthControlled, BasicFungibleFaucet, BasicWallet}, AccountId, }, address::NetworkId, auth::AuthSecretKey, builder::ClientBuilder, - keystore::FilesystemKeyStore, - note::{create_p2id_note, NoteType}, + keystore::{FilesystemKeyStore, Keystore}, + note::{NoteType, P2idNote}, rpc::{Endpoint, GrpcClient}, - transaction::{OutputNote, TransactionRequestBuilder}, + transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; @@ -298,13 +300,13 @@ async fn main() -> Result<(), ClientError> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the account let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -313,7 +315,7 @@ async fn main() -> Result<(), ClientError> { client.add_account(&alice_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); let alice_account_id_bech32 = alice_account.id().to_bech32(NetworkId::Testnet); println!("Alice's account ID: {:?}", alice_account_id_bech32); @@ -333,14 +335,15 @@ async fn main() -> Result<(), ClientError> { let max_supply = Felt::new(1_000_000); // Generate key pair - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the faucet account let faucet_account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) + .with_component(AuthControlled::allow_all()) .build() .unwrap(); @@ -348,7 +351,7 @@ async fn main() -> Result<(), ClientError> { client.add_account(&faucet_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, faucet_account.id()).await.unwrap(); let faucet_account_id_bech32 = faucet_account.id().to_bech32(NetworkId::Testnet); println!("Faucet account ID: {:?}", faucet_account_id_bech32); diff --git a/docs/src/rust-client/creating_notes_in_masm_tutorial.md b/docs/src/rust-client/creating_notes_in_masm_tutorial.md index 2f96ceff..4f831b41 100644 --- a/docs/src/rust-client/creating_notes_in_masm_tutorial.md +++ b/docs/src/rust-client/creating_notes_in_masm_tutorial.md @@ -51,9 +51,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -90,10 +90,12 @@ use miden::core::sys use miden::standards::wallets::basic->wallet # Memory Addresses -const ASSET=0 -const ASSET_HALF=4 -const ACCOUNT_ID_PREFIX=8 -const TAG=10 +# get_assets writes: ASSET_KEY at ASSET_KEY_PTR, ASSET_VALUE at ASSET_KEY_PTR+4 (ASSET_SIZE=8) +const ASSET_KEY_PTR=0 +const ASSET_VALUE_PTR=4 +const ASSET_HALF_VALUE_PTR=8 # half-amount ASSET_VALUE stored here +const ACCOUNT_ID_PREFIX=12 # storage: [prefix, suffix, tag, 0] +const TAG=14 # = ACCOUNT_ID_PREFIX + 2 # => [] begin @@ -101,25 +103,24 @@ begin dropw # => [] - # Get asset contained in note - push.ASSET exec.active_note::get_assets drop drop + # Get asset contained in note into memory (ASSET_KEY at 0, ASSET_VALUE at 4) + push.ASSET_KEY_PTR exec.active_note::get_assets drop drop # => [] - mem_loadw_be.ASSET - # => [ASSET] + # Load ASSET_VALUE and compute half amount + padw push.ASSET_VALUE_PTR mem_loadw_le + # => [av0, av1, av2, av3] (av0 = amount for fungible asset, av1/av2/av3 = 0) - # Compute half amount of asset - swap.3 push.2 div swap.3 - # => [ASSET_HALF] + # Halve the amount (av0 is amount for fungible assets in v0.14) + push.2 div + # => [av0/2, av1, av2, av3] - mem_storew_be.ASSET_HALF dropw + # Store as ASSET_HALF_VALUE + mem_storew_le.ASSET_HALF_VALUE_PTR dropw # => [] - mem_loadw_be.ASSET - # => [ASSET] - - # Receive the entire asset amount to the wallet - call.wallet::receive_asset + # Receive all assets from note into the account wallet + exec.wallet::add_assets_to_account # => [] # Push script hash @@ -130,22 +131,23 @@ begin exec.active_note::get_serial_number # => [SERIAL_NUM, SCRIPT_HASH] - # Increment serial number by 1 - push.1 add + # Increment the last element of the serial number by 1 + # (serial_num[3] is at depth 3; matches Rust: serial_num[3] + 1) + swap.3 push.1 add swap.3 # => [SERIAL_NUM+1, SCRIPT_HASH] - # Load note inputs into memory for recipient and tag + # Load note storage into memory for recipient construction push.ACCOUNT_ID_PREFIX - exec.active_note::get_inputs - # => [num_inputs, dest_ptr, SERIAL_NUM+1, SCRIPT_HASH] + exec.active_note::get_storage + # => [num_storage_items, dest_ptr, SERIAL_NUM+1, SCRIPT_HASH] swap - # => [dest_ptr, num_inputs, SERIAL_NUM+1, SCRIPT_HASH] + # => [dest_ptr, num_storage_items, SERIAL_NUM+1, SCRIPT_HASH] exec.note::build_recipient # => [RECIPIENT] - # Push note type to stack (public note) + # Push note type to stack (public note = 1) push.1 # => [note_type, RECIPIENT] @@ -153,16 +155,24 @@ begin mem_load.TAG # => [tag, note_type, RECIPIENT] - call.output_note::create - # => [note_idx, pad(15) ...] + exec.output_note::create + # => [note_idx] + + # Build [ASSET_KEY, ASSET_HALF_VALUE, note_idx] for move_asset_to_note + # Inputs: [ASSET_KEY, ASSET_VALUE, note_idx, pad(7)] + + # Push ASSET_HALF_VALUE (note_idx moves to depth 4) + padw push.ASSET_HALF_VALUE_PTR mem_loadw_le + # => [ASSET_HALF_VALUE, note_idx] - padw mem_loadw_be.ASSET_HALF - # => [ASSET / 2, note_idx] + # Push ASSET_KEY (ASSET_HALF_VALUE moves to depth 4, note_idx to depth 8) + padw push.ASSET_KEY_PTR mem_loadw_le + # => [ASSET_KEY, ASSET_HALF_VALUE, note_idx] call.wallet::move_asset_to_note - # => [ASSET, note_idx, pad(11)] + # => [pad(16)] - dropw drop + dropw dropw dropw dropw # => [] exec.sys::truncate_stack @@ -173,17 +183,17 @@ end ### How the Assembly Code Works: 1. **Retrieving the asset:** - The note calls `active_note::get_assets` to write the asset contained in the note to memory address 0, defined as `ASSET`. It computes half of the asset and stores the value at memory address 4, defined as `ASSET_HALF`. Finally, the note calls the `wallet::receive_asset` procedure to move the asset contained in the note to the consuming account. + The note calls `active_note::get_assets` to write the asset into memory, with `ASSET_KEY` at address 0 and `ASSET_VALUE` at address 4. It halves the amount in `ASSET_VALUE` and stores it at `ASSET_HALF_VALUE_PTR`. Finally, it calls `wallet::add_assets_to_account` to receive all note assets into the consuming account. 2. **Getting the script hash and serial number:** - The note script calls `active_note::get_script_root` to fetch the script hash and `active_note::get_serial_number` to fetch the current serial number, then increments it by 1 to avoid duplicate recipients. + The note script calls `active_note::get_script_root` to fetch the script hash and `active_note::get_serial_number` to fetch the current serial number, then increments element 3 (the last element) by 1 to avoid duplicate recipients. 3. **Building the `RECIPIENT`:** - The script loads the note inputs into memory with `active_note::get_inputs`, then calls `note::build_recipient`. This computes the inputs commitment and stores the inputs preimage in the advice map, which is required for public notes. + The script loads the note storage into memory with `active_note::get_storage`, then calls `note::build_recipient`. This computes the storage commitment and stores the preimage in the advice map, which is required for public notes. 4. **Creating the note:** - To create the note, the script pushes the note type and tag onto the stack, then calls the `output_note::create` procedure, which returns a pointer to the note. + To create the note, the script pushes the note type and tag onto the stack, then calls the `output_note::create` procedure, which returns the note index. 5. **Moving assets to the note:** - After the note is created, the script loads the half asset value computed in step 1 onto the stack and calls the `wallet::move_asset_to_note` procedure. + After the note is created, the script loads `ASSET_KEY` and `ASSET_HALF_VALUE` from memory onto the stack and calls `wallet::move_asset_to_note` with the note index. 6. **Stack cleanup:** - Finally, the script cleans up the stack by calling `sys::truncate_stack` after creating the note and adding the assets. + Finally, the script cleans up the stack by calling `sys::truncate_stack`. ## Step 3: Rust Program @@ -192,14 +202,14 @@ With the Miden assembly note script written, we can move on to writing the Rust Copy and paste the following code into your `src/main.rs` file. ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::{fs, path::Path, sync::Arc}; use tokio::time::{sleep, Duration}; use miden_client::{ account::{ - component::{BasicFungibleFaucet, BasicWallet}, + component::{AuthControlled, BasicFungibleFaucet, BasicWallet}, Account, }, address::NetworkId, @@ -207,12 +217,12 @@ use miden_client::{ auth::AuthSecretKey, builder::ClientBuilder, crypto::FeltRng, - keystore::FilesystemKeyStore, + keystore::{FilesystemKeyStore, Keystore}, note::{ - Note, NoteAssets, NoteInputs, NoteMetadata, NoteRecipient, NoteTag, NoteType, + Note, NoteAssets, NoteMetadata, NoteRecipient, NoteStorage, NoteTag, NoteType, }, rpc::{Endpoint, GrpcClient}, - transaction::{OutputNote, TransactionRequestBuilder}, + transaction::TransactionRequestBuilder, Client, ClientError, Felt, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; @@ -229,18 +239,18 @@ async fn create_basic_account( let mut init_seed = [0u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); client.add_account(&account, false).await?; - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, account.id()).await.unwrap(); Ok(account) } @@ -252,7 +262,7 @@ async fn create_basic_faucet( let mut init_seed = [0u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let symbol = TokenSymbol::new("MID").unwrap(); let decimals = 8; let max_supply = Felt::new(1_000_000); @@ -260,13 +270,14 @@ async fn create_basic_faucet( let account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) + .with_component(AuthControlled::allow_all()) .build() .unwrap(); client.add_account(&account, false).await?; - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, account.id()).await.unwrap(); Ok(account) } @@ -389,9 +400,9 @@ async fn main() -> Result<(), ClientError> { // Create note metadata and tag let tag = NoteTag::new(0); - let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public, tag); + let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public).with_tag(tag); let note_script = client.code_builder().compile_note_script(&code).unwrap(); - let note_inputs = NoteInputs::new(vec![ + let note_storage = NoteStorage::new(vec![ alice_account.id().prefix().as_felt(), alice_account.id().suffix(), tag.into(), @@ -399,12 +410,12 @@ async fn main() -> Result<(), ClientError> { ]) .unwrap(); - let recipient = NoteRecipient::new(serial_num, note_script.clone(), note_inputs.clone()); + let recipient = NoteRecipient::new(serial_num, note_script.clone(), note_storage.clone()); let vault = NoteAssets::new(vec![mint_amount.into()])?; let custom_note = Note::new(vault, metadata, recipient); let note_req = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(custom_note.clone())]) + .own_output_notes(vec![custom_note.clone()]) .build() .unwrap(); @@ -428,15 +439,15 @@ async fn main() -> Result<(), ClientError> { serial_num[0], serial_num[1], serial_num[2], - Felt::new(serial_num[3].as_int() + 1), + Felt::new(serial_num[3].as_canonical_u64() + 1), ] .into(); - // Reuse the note_script and note_inputs - let recipient = NoteRecipient::new(serial_num_1, note_script, note_inputs); + // Reuse the note_script and note_storage + let recipient = NoteRecipient::new(serial_num_1, note_script, note_storage); // Note: Change metadata to include Bob's account as the creator - let metadata = NoteMetadata::new(bob_account.id(), NoteType::Public, tag); + let metadata = NoteMetadata::new(bob_account.id(), NoteType::Public).with_tag(tag); let asset_amount_1 = FungibleAsset::new(faucet_id, 50).unwrap(); let vault = NoteAssets::new(vec![asset_amount_1.into()])?; @@ -474,24 +485,25 @@ cargo run --release The output will look something like this: ```text -Latest block: 226933 +Latest block: 4186 [STEP 1] Creating new accounts -Alice's account ID: "mtst1qpljtarjtawzcyqqqdcqu53adytw09yw" -Bob's account ID: "mtst1qzaynsxth84vsyqqq0emse6ygcax3j59" +Alice's account ID: "mtst1aqnztxg76d5exyr7ja05pzhvegx3jc84" +Bob's account ID: "mtst1az0mfyzm3xqe2yrezucvmc24dv5gset0" Deploying a new fungible faucet. -Faucet account ID: "mtst1qpqpq6z8vrqvugqqqwjdnajgvurs9zgl" +Faucet account ID: "mtst1ary7kplxvatxkgpes4llcc53yu8px433" [STEP 2] Mint tokens with P2ID -0 consumable notes found for account mtst1qpljtarjtawzcyqqqdcqu53adytw09yw. Waiting... -0 consumable notes found for account mtst1qpljtarjtawzcyqqqdcqu53adytw09yw. Waiting... +Minted tokens. TX: 0x8577213057226b7d0545d73f6e1bc416354a324089450cb859f5784c133d4cc0 +0 consumable notes found for account mtst1aqnztxg76d5exyr7ja05pzhvegx3jc84. Waiting... +Consumed minted note. TX: 0xd93e791d3283192df121de4cf938a4f9cfaed48f4e593e1b82d147e2d642b7bd [STEP 3] Create iterative output note -View transaction on MidenScan: https://testnet.midenscan.com/tx/0x335061a434ccccbf9619052bdeacbc71b6e755b24f0ead0c3741a3b0954c78af +View transaction on MidenScan: https://testnet.midenscan.com/tx/0xcd71a1d87c60ab7632a7836723fff4014b02992ef7ea5d3fe2030a971e795a8a [STEP 4] Bob consumes the note and creates a copy -Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0xa39acf2bb965b4669b91bf564e8aa2987a9fc86ee350cd159ad5db1054cb67ab +Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x4d91519c180874c931480fa58620f864fd7c7aada35ada2d40082291298084bb Account delta: AccountVaultDelta { fungible: FungibleAssetDelta({V0(Accoun ``` diff --git a/docs/src/rust-client/custom_note_how_to.md b/docs/src/rust-client/custom_note_how_to.md index 0acc77cf..7fc58599 100644 --- a/docs/src/rust-client/custom_note_how_to.md +++ b/docs/src/rust-client/custom_note_how_to.md @@ -59,7 +59,6 @@ use miden::standards::wallets::basic->wallet # ================================================================================================= const EXPECTED_DIGEST_PTR=0 -const ASSET_PTR=100 # ERRORS # ================================================================================================= @@ -69,7 +68,7 @@ const ERROR_DIGEST_MISMATCH="Expected digest does not match computed digest" #! Inputs (arguments): [HASH_PREIMAGE_SECRET] #! Outputs: [] #! -#! Note inputs are assumed to be as follows: +#! Note storage is assumed to be as follows: #! => EXPECTED_DIGEST begin # => HASH_PREIMAGE_SECRET @@ -77,11 +76,11 @@ begin hash # => [DIGEST] - # Writing the note inputs to memory - push.EXPECTED_DIGEST_PTR exec.active_note::get_inputs drop drop + # Writing the note storage to memory + push.EXPECTED_DIGEST_PTR exec.active_note::get_storage drop drop - # Pad stack and load expected digest from memory - padw push.EXPECTED_DIGEST_PTR mem_loadw_be + # Pad stack and load expected digest from memory (LE: mem[addr] ends up on top) + padw push.EXPECTED_DIGEST_PTR mem_loadw_le # => [EXPECTED_DIGEST, DIGEST] # Assert that the note input matches the digest @@ -93,19 +92,8 @@ begin # If the check is successful, we allow for the asset to be consumed # --------------------------------------------------------------------------------------------- - # Write the asset in note to memory address ASSET_PTR - push.ASSET_PTR exec.active_note::get_assets - # => [num_assets, dest_ptr] - - drop - # => [dest_ptr] - - # Load asset from memory - mem_loadw_be - # => [ASSET] - - # Call receive asset in wallet - call.wallet::receive_asset + # Add all assets from the note to the account + exec.wallet::add_assets_to_account # => [] end ``` @@ -113,15 +101,15 @@ end ### How the assembly code works: 1. **Constants and Error Handling:** - The code defines memory pointers (`EXPECTED_DIGEST_PTR` and `ASSET_PTR`) for better code organization and an error message for digest mismatches. + The code defines a memory pointer (`EXPECTED_DIGEST_PTR`) for storing the expected hash and an error message for digest mismatches. 2. **Passing the Secret:** The secret number is passed as `Note Arguments` into the note. 3. **Hashing the Secret:** - The `hash` instruction applies a hash permutation to the secret number, resulting in a digest that takes up four stack elements. + The `hash` instruction applies a Poseidon2 hash permutation to the secret number, resulting in a digest that takes up four stack elements. 4. **Digest Comparison:** - The assembly code loads the expected digest from the note inputs stored in memory and compares it with the computed hash. If they don't match, the transaction fails with a clear error message. + The assembly code loads the expected digest from note storage into memory, then reads it back with `mem_loadw_le` (which places `mem[addr]` on top, matching the hash output order) and compares with the computed hash. If they don't match, the transaction fails with a clear error message. 5. **Asset Transfer:** - If the hash of the number passed in as `Note Arguments` matches the hash stored in the note inputs, the script continues, and the asset stored in the note is loaded from memory and passed to Bob's wallet via the `wallet::receive_asset` function. + If the hash matches, `wallet::add_assets_to_account` transfers all note assets into the consuming account's vault. ### 5. Consuming the note @@ -134,27 +122,27 @@ With the note created, Bob can now consume itβ€”but only if he provides the corr The following Rust code demonstrates how to implement the steps outlined above using the Miden client library: ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::{fs, path::Path, sync::Arc}; use tokio::time::{sleep, Duration}; use miden_client::{ account::{ - component::{BasicFungibleFaucet, BasicWallet}, + component::{AuthControlled, BasicFungibleFaucet, BasicWallet}, Account, }, address::NetworkId, auth::AuthSecretKey, builder::ClientBuilder, crypto::FeltRng, - keystore::FilesystemKeyStore, + keystore::{FilesystemKeyStore, Keystore}, note::{ - Note, NoteAssets, NoteInputs, NoteMetadata, NoteRecipient, NoteTag, NoteType, + Note, NoteAssets, NoteMetadata, NoteRecipient, NoteStorage, NoteTag, NoteType, }, rpc::{Endpoint, GrpcClient}, store::TransactionFilter, - transaction::{OutputNote, TransactionId, TransactionRequestBuilder, TransactionStatus}, + transaction::{TransactionId, TransactionRequestBuilder, TransactionStatus}, Client, ClientError, Felt, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; @@ -172,18 +160,18 @@ async fn create_basic_account( let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); client.add_account(&account, false).await?; - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, account.id()).await.unwrap(); Ok(account) } @@ -195,7 +183,7 @@ async fn create_basic_faucet( let mut init_seed = [0u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let symbol = TokenSymbol::new("MID").unwrap(); let decimals = 8; let max_supply = Felt::new(1_000_000); @@ -203,13 +191,14 @@ async fn create_basic_faucet( let account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) + .with_component(AuthControlled::allow_all()) .build() .unwrap(); client.add_account(&account, false).await?; - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, account.id()).await.unwrap(); Ok(account) } @@ -349,16 +338,16 @@ async fn main() -> Result<(), ClientError> { let serial_num = client.rng().draw_word(); let note_script = client.code_builder().compile_note_script(code).unwrap(); - let note_inputs = NoteInputs::new(digest.to_vec()).unwrap(); - let recipient = NoteRecipient::new(serial_num, note_script, note_inputs); + let note_storage = NoteStorage::new(digest.to_vec()).unwrap(); + let recipient = NoteRecipient::new(serial_num, note_script, note_storage); let tag = NoteTag::new(0); - let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public, tag); + let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public).with_tag(tag); let vault = NoteAssets::new(vec![mint_amount.into()])?; let custom_note = Note::new(vault, metadata, recipient); println!("note hash: {:?}", custom_note.id().to_hex()); let note_request = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(custom_note.clone())]) + .own_output_notes(vec![custom_note.clone()]) .build() .unwrap(); @@ -401,11 +390,11 @@ The output of our program will look something like this: Latest block: 226943 [STEP 1] Creating new accounts -Alice's account ID: "mtst1qqufkq3xr0rr5yqqqwgrc20ctythccy6" -Bob's account ID: "mtst1qz76c9fvhvms2yqqqvvw8tf6m5h86y2h" +Alice's account ID: "" +Bob's account ID: "" Deploying a new fungible faucet. -Faucet account ID: "mtst1qpwsgjstpwvykgqqqwwzgz3u5vwuuywe" +Faucet account ID: "" [STEP 2] Mint tokens with P2ID Note 0x88d8c4a50c0e6342e58026b051fb6038867de21d3bd3963aec67fd6c45861faf not found. Waiting... diff --git a/docs/src/rust-client/delegated_proving_tutorial.md b/docs/src/rust-client/delegated_proving_tutorial.md index 81670e87..e3413ce8 100644 --- a/docs/src/rust-client/delegated_proving_tutorial.md +++ b/docs/src/rust-client/delegated_proving_tutorial.md @@ -48,9 +48,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -65,16 +65,15 @@ We construct a `LocalTransactionProver` for this walkthrough. ```rust no_run use miden_client::auth::AuthSecretKey; -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::sync::Arc; use miden_client::{ account::component::BasicWallet, builder::ClientBuilder, - keystore::FilesystemKeyStore, + keystore::{FilesystemKeyStore, Keystore}, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::{ LocalTransactionProver, ProvingOptions, @@ -114,18 +113,18 @@ async fn main() -> Result<(), ClientError> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountImmutableCode) .storage_mode(AccountStorageMode::Private) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); client.add_account(&alice_account, false).await?; - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); // ------------------------------------------------------------------------- // Setup the local tx prover @@ -172,15 +171,11 @@ async fn main() -> Result<(), ClientError> { client.sync_state().await.unwrap(); - let account_record = client + let account = client .get_account(alice_account.id()) .await .unwrap() - .unwrap(); - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("alice account is missing full account data"), - }; + .expect("alice account not found"); println!("Alice nonce has increased: {:?}", account.nonce()); diff --git a/docs/src/rust-client/foreign_procedure_invocation_tutorial.md b/docs/src/rust-client/foreign_procedure_invocation_tutorial.md index abd13bb8..f7df1084 100644 --- a/docs/src/rust-client/foreign_procedure_invocation_tutorial.md +++ b/docs/src/rust-client/foreign_procedure_invocation_tutorial.md @@ -53,18 +53,18 @@ use miden::core::sys const COUNT_READER_SLOT = word("miden::tutorials::count_reader") -# => [account_id_prefix, account_id_suffix, get_count_proc_hash] +# => [account_id_suffix, account_id_prefix, PROC_HASH(4), foreign_procedure_inputs(16)] pub proc copy_count exec.tx::execute_foreign_procedure - # => [count] + # => [count, pad(12)] push.COUNT_READER_SLOT[0..2] - # [slot_id_prefix, slot_id_suffix, count] + # [slot_id_prefix, slot_id_suffix, count, pad(12)] exec.native_account::set_item - # => [OLD_VALUE] + # => [OLD_VALUE, pad(12)] - dropw + dropw dropw dropw dropw # => [] exec.sys::truncate_stack @@ -79,9 +79,14 @@ To call the `get_count` procedure, we push its hash along with the counter contr This is what the stack state should look like before we call `tx::execute_foreign_procedure`: ```text -# => [account_id_prefix, account_id_suffix, GET_COUNT_HASH] +# => [account_id_suffix, account_id_prefix, GET_COUNT_HASH, foreign_procedure_inputs(16)] ``` +`execute_foreign_procedure` always requires exactly 16 `foreign_procedure_inputs` on the stack +below the procedure hash and account ID. Since `get_count` takes no arguments, we pass 16 zero +words (`padw padw padw padw`) as the inputs. After the call, the procedure returns 16 output +elements; the count word sits at the top and we clean up the rest with `dropw dropw dropw dropw`. + After calling the `get_count` procedure in the counter contract, we save the count into the `miden::tutorials::count_reader` storage slot. @@ -94,14 +99,17 @@ use external_contract::count_reader_contract use miden::core::sys begin - push.{get_count_proc_hash} - # => [GET_COUNT_HASH] + padw padw padw padw + # => [pad(16)] - push.{account_id_suffix} - # => [account_id_suffix, GET_COUNT_HASH] + push.{get_count_proc_hash} + # => [GET_COUNT_HASH, pad(16)] push.{account_id_prefix} - # => [account_id_prefix, account_id_suffix, GET_COUNT_HASH] + # => [account_id_prefix, GET_COUNT_HASH, pad(16)] + + push.{account_id_suffix} + # => [account_id_suffix, account_id_prefix, GET_COUNT_HASH, pad(16)] call.count_reader_contract::copy_count # => [] @@ -116,49 +124,45 @@ end ### Step 3: Set up your `src/main.rs` file: ```rust no_run -use miden_client::auth::NoAuth; -use miden_client::transaction::TransactionKernel; use rand::RngCore; use std::{fs, path::Path, sync::Arc, time::Duration}; use tokio::time::sleep; use miden_client::{ + account::{ + component::AccountComponentMetadata, AccountBuilder, AccountComponent, + AccountStorageMode, AccountType, StorageSlot, StorageSlotName, + }, + account::AccountId, assembly::{ - Assembler, CodeBuilder, DefaultSourceManager, + Library, Module, ModuleKind, Path as AssemblyPath, }, + auth::NoAuth, builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{domain::account::AccountStorageRequirements, Endpoint, GrpcClient}, - store::AccountRecordData, - transaction::{ForeignAccount, TransactionRequestBuilder}, - ClientError, Felt, + transaction::{ForeignAccount, TransactionKernel, TransactionRequestBuilder}, + ClientError, Word, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; -use miden_client::{ - account::{ - AccountBuilder, AccountComponent, AccountId, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, - }, - Word, -}; fn create_library( - assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); + let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), source_code, - source_manager.clone(), + source_manager, )?; - let library = assembler.clone().assemble_library([module])?; + let library = assembler.assemble_library([module])?; Ok(library) } @@ -169,7 +173,6 @@ async fn main() -> Result<(), ClientError> { let timeout_ms = 10_000; let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms)); - // Initialize keystore let keystore_path = std::path::PathBuf::from("./keystore"); let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap()); @@ -191,14 +194,9 @@ async fn main() -> Result<(), ClientError> { // ------------------------------------------------------------------------- println!("\n[STEP 1] Creating count reader contract."); - // Load the MASM file for the counter contract let count_reader_path = Path::new("../masm/accounts/count_reader.masm"); let count_reader_code = fs::read_to_string(count_reader_path).unwrap(); - // Prepare assembler (debug mode = true) - let assembler = TransactionKernel::assembler(); - - // Compile the account code into `AccountComponent` with one storage slot let count_reader_slot_name = StorageSlotName::new("miden::tutorials::count_reader").expect("valid slot name"); let count_reader_component_code = CodeBuilder::new() @@ -210,15 +208,13 @@ async fn main() -> Result<(), ClientError> { count_reader_slot_name.clone(), Word::default(), )], + AccountComponentMetadata::new("external_contract::count_reader_contract", AccountType::all()), ) - .unwrap() - .with_supports_all_types(); + .unwrap(); - // Init seed for the counter contract let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - // Build the new `Account` with the component let count_reader_contract = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountImmutableCode) .storage_mode(AccountStorageMode::Public) @@ -229,7 +225,7 @@ async fn main() -> Result<(), ClientError> { println!( "count_reader hash: {:?}", - count_reader_contract.commitment() + count_reader_contract.to_commitment() ); println!("contract id: {:?}", count_reader_contract.id()); @@ -255,12 +251,12 @@ Latest block: 226976 [STEP 1] Creating count reader contract. count_reader hash: RpoDigest([15888177100833057221, 15548657445961063290, 5580812380698193124, 9604096693288041818]) -contract id: "mtst1qp3ca3adt34euqqqqwt488x34qnnd495" +contract id: "" ``` -## Step 4: Build and read the state of the counter contract deployed on testnet +## Step 4: Import the pre-deployed counter contract -Add this snippet to the end of your file in the `main()` function that we created in the previous step: +The FPI call needs a counter contract already deployed on-chain. We import the counter contract that was deployed in the [counter contract tutorial](./counter_contract_tutorial.md) by its testnet address: ```rust ignore // ------------------------------------------------------------------------- @@ -270,7 +266,7 @@ println!("\n[STEP 2] Building counter contract from public state"); // Define the Counter Contract account id from counter contract deploy let (_, counter_contract_id) = - AccountId::from_bech32("mtst1arjemrxne8lj5qz4mg9c8mtyxg954483").unwrap(); + AccountId::from_bech32("mtst1apsd609q5966cqra992t4a00tgstrkfk").unwrap(); println!("counter contract id: {:?}", counter_contract_id); @@ -279,24 +275,17 @@ client .await .unwrap(); -let counter_contract_details = client +let counter_contract = client .get_account(counter_contract_id) .await .unwrap() .expect("counter contract not found"); - -let counter_contract = match counter_contract_details.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), -}; println!( "Account details: {:?}", counter_contract.storage().slots().first().unwrap() ); ``` -This step uses the logic we explained in the [Public Account Interaction Tutorial](./public_account_interaction_tutorial.md) to read the state of the Counter contract and import it to the client locally. - ## Step 5: Call the counter contract via foreign procedure invocation Add this snippet to the end of your file in the `main()` function: @@ -305,50 +294,49 @@ Add this snippet to the end of your file in the `main()` function: // ------------------------------------------------------------------------- // STEP 3: Call the Counter Contract via Foreign Procedure Invocation (FPI) // ------------------------------------------------------------------------- -println!("\n[STEP 3] Call counter contract with FPI from count copy contract"); +println!("\n[STEP 3] Call counter contract with FPI from count reader contract"); +// Derive the get_count procedure hash from the locally compiled counter library. let counter_contract_path = Path::new("../masm/accounts/counter.masm"); let counter_contract_code = fs::read_to_string(counter_contract_path).unwrap(); -let counter_contract_component_code = CodeBuilder::new() +// Compile the counter as a component (same path as the deploy binary) to get +// the correct procedure root that matches the on-chain MAST. +let counter_component_code = CodeBuilder::new() .compile_component_code("external_contract::counter_contract", &counter_contract_code) .unwrap(); -let counter_contract_component = - AccountComponent::new(counter_contract_component_code, vec![]) - .unwrap() - .with_supports_all_types(); +let counter_component = AccountComponent::new( + counter_component_code, + vec![], + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), +) +.unwrap(); -// Getting the hash of the `get_count` procedure -let library = counter_contract_component.component_code().as_library(); -let get_count_hash = library +let get_count_root = counter_component + .component_code() + .as_library() .get_procedure_root_by_path("external_contract::counter_contract::get_count") - .expect("get_count export not found") - .as_elements() - .iter() - .map(|f: &Felt| format!("{}", f.as_int())) - .collect::>() - .join("."); - -println!("get count hash: {:?}", get_count_hash); -println!("counter id prefix: {:?}", counter_contract.id().prefix()); -println!("suffix: {:?}", counter_contract.id().suffix()); - -// Build the script that calls the count_copy_contract + .expect("get_count export not found"); +let get_count_hash = format!("{}", get_count_root); + +println!("get_count hash: {:?}", get_count_hash); +println!("counter id prefix: {:?}", counter_contract_id.prefix()); +println!("counter id suffix: {:?}", counter_contract_id.suffix()); + let script_path = Path::new("../masm/scripts/reader_script.masm"); let script_code_original = fs::read_to_string(script_path).unwrap(); let script_code = script_code_original .replace("{get_count_proc_hash}", &get_count_hash) .replace( "{account_id_suffix}", - &counter_contract.id().suffix().to_string(), + &counter_contract_id.suffix().as_canonical_u64().to_string(), ) .replace( "{account_id_prefix}", - &counter_contract.id().prefix().to_string(), + &u64::from(counter_contract_id.prefix()).to_string(), ); let account_component_lib = create_library( - assembler.clone(), "external_contract::count_reader_contract", &count_reader_code, ) @@ -364,14 +352,12 @@ let tx_script = client let foreign_account = ForeignAccount::public(counter_contract_id, AccountStorageRequirements::default()).unwrap(); -// Build a transaction request with the custom script let tx_request = TransactionRequestBuilder::new() .foreign_accounts([foreign_account]) .custom_script(tx_script) .build() .unwrap(); -// Execute and submit the transaction let tx_id = client .submit_new_transaction(count_reader_contract.id(), tx_request) .await @@ -383,12 +369,10 @@ println!( ); client.sync_state().await.unwrap(); - sleep(Duration::from_secs(5)).await; - client.sync_state().await.unwrap(); -// Retrieve updated contract data to see the incremented counter +// Retrieve final state to confirm the count was copied. let counter_slot_name = StorageSlotName::new("miden::tutorials::counter").expect("valid slot name"); let account_1 = client @@ -396,24 +380,16 @@ let account_1 = client .await .unwrap() .expect("counter contract not found"); -let account_1 = match account_1.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), -}; println!( "counter contract storage: {:?}", account_1.storage().get_item(&counter_slot_name) ); -let account_2_record = client +let account_2 = client .get_account(count_reader_contract.id()) .await .unwrap() .expect("count reader contract not found"); -let account_2 = match account_2_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("count reader contract is missing full account data"), -}; println!( "count reader contract storage: {:?}", account_2.storage().get_item(&count_reader_slot_name) @@ -429,49 +405,40 @@ In this tutorial created a smart contract that calls the `get_count` procedure i The final `src/main.rs` file should look like this: ```rust no_run -use miden_client::auth::NoAuth; -use miden_client::transaction::TransactionKernel; use rand::RngCore; use std::{fs, path::Path, sync::Arc, time::Duration}; use tokio::time::sleep; use miden_client::{ + account::{ + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountId, + AccountStorageMode, AccountType, StorageSlot, StorageSlotName, + }, assembly::{ - Assembler, - CodeBuilder, - DefaultSourceManager, - Module, - ModuleKind, + CodeBuilder, DefaultSourceManager, Library, Module, ModuleKind, Path as AssemblyPath, }, + auth::NoAuth, builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{domain::account::AccountStorageRequirements, Endpoint, GrpcClient}, - store::AccountRecordData, - transaction::{ForeignAccount, TransactionRequestBuilder}, - ClientError, Felt, + transaction::{ForeignAccount, TransactionKernel, TransactionRequestBuilder}, + ClientError, Word, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; -use miden_client::{ - account::{ - AccountBuilder, AccountComponent, AccountId, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, - }, - Word, -}; fn create_library( - assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); + let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), source_code, - source_manager.clone(), + source_manager, )?; - let library = assembler.clone().assemble_library([module])?; + let library = assembler.assemble_library([module])?; Ok(library) } @@ -482,7 +449,6 @@ async fn main() -> Result<(), ClientError> { let timeout_ms = 10_000; let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms)); - // Initialize keystore let keystore_path = std::path::PathBuf::from("./keystore"); let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap()); @@ -504,18 +470,16 @@ async fn main() -> Result<(), ClientError> { // ------------------------------------------------------------------------- println!("\n[STEP 1] Creating count reader contract."); - // Load the MASM file for the counter contract let count_reader_path = Path::new("../masm/accounts/count_reader.masm"); let count_reader_code = fs::read_to_string(count_reader_path).unwrap(); - // Prepare assembler (debug mode = true) - let assembler = TransactionKernel::assembler(); - - // Compile the account code into `AccountComponent` with one storage slot let count_reader_slot_name = StorageSlotName::new("miden::tutorials::count_reader").expect("valid slot name"); let count_reader_component_code = CodeBuilder::new() - .compile_component_code("external_contract::count_reader_contract", &count_reader_code) + .compile_component_code( + "external_contract::count_reader_contract", + &count_reader_code, + ) .unwrap(); let count_reader_component = AccountComponent::new( count_reader_component_code, @@ -523,15 +487,16 @@ async fn main() -> Result<(), ClientError> { count_reader_slot_name.clone(), Word::default(), )], + AccountComponentMetadata::new( + "external_contract::count_reader_contract", + AccountType::all(), + ), ) - .unwrap() - .with_supports_all_types(); + .unwrap(); - // Init seed for the counter contract let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - // Build the new `Account` with the component let count_reader_contract = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountImmutableCode) .storage_mode(AccountStorageMode::Public) @@ -542,9 +507,9 @@ async fn main() -> Result<(), ClientError> { println!( "count_reader hash: {:?}", - count_reader_contract.commitment() + count_reader_contract.to_commitment() ); - println!("contract id: {:?}", count_reader_contract.id()); + println!("count_reader id: {:?}", count_reader_contract.id()); client .add_account(&count_reader_contract, false) @@ -558,7 +523,7 @@ async fn main() -> Result<(), ClientError> { // Define the Counter Contract account id from counter contract deploy let (_, counter_contract_id) = - AccountId::from_bech32("mtst1arjemrxne8lj5qz4mg9c8mtyxg954483").unwrap(); + AccountId::from_bech32("mtst1apsd609q5966cqra992t4a00tgstrkfk").unwrap(); println!("counter contract id: {:?}", counter_contract_id); @@ -567,16 +532,11 @@ async fn main() -> Result<(), ClientError> { .await .unwrap(); - let counter_contract_details = client + let counter_contract = client .get_account(counter_contract_id) .await .unwrap() .expect("counter contract not found"); - - let counter_contract = match counter_contract_details.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), - }; println!( "Account details: {:?}", counter_contract.storage().slots().first().unwrap() @@ -585,50 +545,48 @@ async fn main() -> Result<(), ClientError> { // ------------------------------------------------------------------------- // STEP 3: Call the Counter Contract via Foreign Procedure Invocation (FPI) // ------------------------------------------------------------------------- - println!("\n[STEP 3] Call counter contract with FPI from count copy contract"); + println!("\n[STEP 3] Call counter contract with FPI from count reader contract"); let counter_contract_path = Path::new("../masm/accounts/counter.masm"); let counter_contract_code = fs::read_to_string(counter_contract_path).unwrap(); - let counter_contract_component_code = CodeBuilder::new() + // Compile the counter as a component (same path as the deploy binary) to get + // the correct procedure root that matches the on-chain MAST. + let counter_component_code = CodeBuilder::new() .compile_component_code("external_contract::counter_contract", &counter_contract_code) .unwrap(); - let counter_contract_component = - AccountComponent::new(counter_contract_component_code, vec![]) - .unwrap() - .with_supports_all_types(); - - // Getting the hash of the `get_count` procedure - let library = counter_contract_component.component_code().as_library(); - let get_count_hash = library + let counter_component = AccountComponent::new( + counter_component_code, + vec![], + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), + ) + .unwrap(); + + let get_count_root = counter_component + .component_code() + .as_library() .get_procedure_root_by_path("external_contract::counter_contract::get_count") - .expect("get_count export not found") - .as_elements() - .iter() - .map(|f: &Felt| format!("{}", f.as_int())) - .collect::>() - .join("."); - - println!("get count hash: {:?}", get_count_hash); + .expect("get_count export not found"); + let get_count_hash = format!("{}", get_count_root); + + println!("get_count hash: {:?}", get_count_hash); println!("counter id prefix: {:?}", counter_contract_id.prefix()); - println!("suffix: {:?}", counter_contract_id.suffix()); + println!("counter id suffix: {:?}", counter_contract_id.suffix()); - // Build the script that calls the count_copy_contract let script_path = Path::new("../masm/scripts/reader_script.masm"); let script_code_original = fs::read_to_string(script_path).unwrap(); let script_code = script_code_original .replace("{get_count_proc_hash}", &get_count_hash) .replace( "{account_id_suffix}", - &counter_contract_id.suffix().to_string(), + &counter_contract_id.suffix().as_canonical_u64().to_string(), ) .replace( "{account_id_prefix}", - &counter_contract_id.prefix().to_string(), + &u64::from(counter_contract_id.prefix()).to_string(), ); let account_component_lib = create_library( - assembler.clone(), "external_contract::count_reader_contract", &count_reader_code, ) @@ -642,16 +600,15 @@ async fn main() -> Result<(), ClientError> { .unwrap(); let foreign_account = - ForeignAccount::public(counter_contract_id, AccountStorageRequirements::default()).unwrap(); + ForeignAccount::public(counter_contract_id, AccountStorageRequirements::default()) + .unwrap(); - // Build a transaction request with the custom script let tx_request = TransactionRequestBuilder::new() .foreign_accounts([foreign_account]) .custom_script(tx_script) .build() .unwrap(); - // Execute and submit the transaction let tx_id = client .submit_new_transaction(count_reader_contract.id(), tx_request) .await @@ -663,12 +620,10 @@ async fn main() -> Result<(), ClientError> { ); client.sync_state().await.unwrap(); - sleep(Duration::from_secs(5)).await; - client.sync_state().await.unwrap(); - // Retrieve updated contract data to see the incremented counter + // Retrieve final state to confirm the count was copied. let counter_slot_name = StorageSlotName::new("miden::tutorials::counter").expect("valid slot name"); let account_1 = client @@ -676,26 +631,16 @@ async fn main() -> Result<(), ClientError> { .await .unwrap() .expect("counter contract not found"); - let account_1 = match account_1.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), - }; println!( "counter contract storage: {:?}", account_1.storage().get_item(&counter_slot_name) ); - let account_2_record = client + let account_2 = client .get_account(count_reader_contract.id()) .await .unwrap() .expect("count reader contract not found"); - let account_2 = match account_2_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => { - panic!("count reader contract is missing full account data") - } - }; println!( "count reader contract storage: {:?}", account_2.storage().get_item(&count_reader_slot_name) @@ -705,75 +650,7 @@ async fn main() -> Result<(), ClientError> { } ``` -The output of our program will look something like this: - -```text -Latest block: 17916 - -[STEP 1] Creating count reader contract. -count_reader hash: RpoDigest([17106452548071357259, 1177663122773866223, 12129142941281960455, 8269441041947541276]) -contract id: "0x4e79c8d2334239000000197081e311" - -[STEP 2] Building counter contract from public state -Account details: Value([0, 0, 0, 2]) - -[STEP 3] Call Counter Contract with FPI from Count Copy Contract -get count hash: "0x92495ca54d519eb5e4ba22350f837904d3895e48d74d8079450f19574bb84cb6" -counter id prefix: V0(AccountIdPrefixV0 { prefix: 1170938688336660224 }) -suffix: 204650730194688 -Stack state before step 2248: -β”œβ”€β”€ 0: 111 -β”œβ”€β”€ 1: 1170938688336660224 -β”œβ”€β”€ 2: 204650730194688 -β”œβ”€β”€ 3: 13136076846856212293 -β”œβ”€β”€ 4: 8755083262635706835 -β”œβ”€β”€ 5: 322432949672917732 -β”œβ”€β”€ 6: 13086986961113860498 -β”œβ”€β”€ 7: 0 -β”œβ”€β”€ 8: 0 -β”œβ”€β”€ 9: 0 -β”œβ”€β”€ 10: 0 -β”œβ”€β”€ 11: 0 -β”œβ”€β”€ 12: 0 -β”œβ”€β”€ 13: 0 -β”œβ”€β”€ 14: 0 -β”œβ”€β”€ 15: 0 -β”œβ”€β”€ 16: 0 -β”œβ”€β”€ 17: 0 -β”œβ”€β”€ 18: 0 -β”œβ”€β”€ 19: 0 -β”œβ”€β”€ 20: 0 -β”œβ”€β”€ 21: 0 -└── 22: 0 - -Stack state before step 3224: -β”œβ”€β”€ 0: 2 -β”œβ”€β”€ 1: 0 -β”œβ”€β”€ 2: 0 -β”œβ”€β”€ 3: 0 -β”œβ”€β”€ 4: 0 -β”œβ”€β”€ 5: 0 -β”œβ”€β”€ 6: 0 -β”œβ”€β”€ 7: 0 -β”œβ”€β”€ 8: 0 -β”œβ”€β”€ 9: 0 -β”œβ”€β”€ 10: 0 -β”œβ”€β”€ 11: 0 -β”œβ”€β”€ 12: 0 -β”œβ”€β”€ 13: 0 -β”œβ”€β”€ 14: 0 -β”œβ”€β”€ 15: 0 -β”œβ”€β”€ 16: 0 -β”œβ”€β”€ 17: 0 -β”œβ”€β”€ 18: 0 -β”œβ”€β”€ 19: 0 -β”œβ”€β”€ 20: 0 -└── 21: 0 - -View transaction on MidenScan: https://testnet.midenscan.com/tx/0x7144cf2648a7001a9972aed73596db070a679b467fec83263846a5a4f8eb74e6 -counter contract storage: Ok(RpoDigest([0, 0, 0, 2])) -count reader contract storage: Ok(RpoDigest([0, 0, 0, 2])) -``` +The output will show the count reader contract being created, the counter contract being imported from testnet, and finally both storage slots reflecting the same count value after the FPI transaction is confirmed. ### Running the example diff --git a/docs/src/rust-client/mappings_in_masm_how_to.md b/docs/src/rust-client/mappings_in_masm_how_to.md index e88a5c33..46ab6e87 100644 --- a/docs/src/rust-client/mappings_in_masm_how_to.md +++ b/docs/src/rust-client/mappings_in_masm_how_to.md @@ -162,15 +162,14 @@ use miden_client::{ builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; use miden_client::{ account::{ - AccountBuilder, AccountComponent, AccountStorageMode, AccountType, StorageMap, StorageSlot, - StorageSlotName, + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode, + AccountType, StorageMap, StorageSlot, StorageSlotName, }, Felt, Word, }; @@ -179,7 +178,7 @@ fn create_library( assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), @@ -242,10 +241,12 @@ async fn main() -> Result<(), ClientError> { let component_code = CodeBuilder::new() .compile_component_code("miden_by_example::mapping_example_contract", &account_code) .unwrap(); - let mapping_contract_component = - AccountComponent::new(component_code, vec![empty_storage_slot, storage_slot_map]) - .unwrap() - .with_supports_all_types(); + let mapping_contract_component = AccountComponent::new( + component_code, + vec![empty_storage_slot, storage_slot_map], + AccountComponentMetadata::new("miden_by_example::mapping_example_contract", AccountType::all()), + ) + .unwrap(); // Init seed for the counter contract let mut init_seed = [0_u8; 32]; @@ -308,15 +309,11 @@ async fn main() -> Result<(), ClientError> { client.sync_state().await.unwrap(); - let account_record = client + let account = client .get_account(mapping_example_contract.id()) .await .unwrap() .expect("mapping contract not found"); - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("mapping contract is missing full account data"), - }; let key = [Felt::new(0), Felt::new(0), Felt::new(0), Felt::new(0)].into(); println!( "Mapping state\n Slot: {:?}\n Key: {:?}\n Value: {:?}", diff --git a/docs/src/rust-client/mint_consume_create_tutorial.md b/docs/src/rust-client/mint_consume_create_tutorial.md index d8c06b7f..302aca40 100644 --- a/docs/src/rust-client/mint_consume_create_tutorial.md +++ b/docs/src/rust-client/mint_consume_create_tutorial.md @@ -174,7 +174,7 @@ for _ in 1..=4 { let send_amount = 50; let fungible_asset = FungibleAsset::new(faucet_account.id(), send_amount).unwrap(); - let p2id_note = create_p2id_note( + let p2id_note = P2idNote::create( alice_account.id(), target_account_id, vec![fungible_asset.into()], @@ -186,9 +186,8 @@ for _ in 1..=4 { } // Specifying output notes and creating a tx request to create them -let output_notes: Vec = p2id_notes.into_iter().map(OutputNote::Full).collect(); let transaction_request = TransactionRequestBuilder::new() - .own_output_notes(output_notes) + .own_output_notes(p2id_notes) .build() .unwrap(); @@ -222,7 +221,7 @@ let target_account_id = AccountId::dummy( let send_amount = 50; let fungible_asset = FungibleAsset::new(faucet_account.id(), send_amount).unwrap(); -let p2id_note = create_p2id_note( +let p2id_note = P2idNote::create( alice_account.id(), target_account_id, vec![fungible_asset.into()], @@ -232,7 +231,7 @@ let p2id_note = create_p2id_note( )?; let transaction_request = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(p2id_note)]) + .own_output_notes(vec![p2id_note]) .build() .unwrap(); @@ -250,23 +249,23 @@ Note: _In a production environment do not use `AccountId::dummy()`, this is simp Your `src/main.rs` function should now look like this: ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::sync::Arc; use tokio::time::Duration; use miden_client::{ account::{ - component::{BasicFungibleFaucet, BasicWallet}, + component::{AuthControlled, BasicFungibleFaucet, BasicWallet}, AccountId, }, address::NetworkId, auth::AuthSecretKey, builder::ClientBuilder, - keystore::FilesystemKeyStore, - note::{create_p2id_note, NoteAttachment, NoteType}, + keystore::{FilesystemKeyStore, Keystore}, + note::{NoteAttachment, NoteType, P2idNote}, rpc::{Endpoint, GrpcClient}, - transaction::{OutputNote, TransactionRequestBuilder}, + transaction::TransactionRequestBuilder, ClientError, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; @@ -310,13 +309,13 @@ async fn main() -> Result<(), ClientError> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the account let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -325,7 +324,7 @@ async fn main() -> Result<(), ClientError> { client.add_account(&alice_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); let alice_account_id_bech32 = alice_account.id().to_bech32(NetworkId::Testnet); println!("Alice's account ID: {:?}", alice_account_id_bech32); @@ -345,14 +344,15 @@ async fn main() -> Result<(), ClientError> { let max_supply = Felt::new(1_000_000); // Generate key pair - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the faucet account let faucet_account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) + .with_component(AuthControlled::allow_all()) .build() .unwrap(); @@ -360,7 +360,7 @@ async fn main() -> Result<(), ClientError> { client.add_account(&faucet_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, faucet_account.id()).await.unwrap(); let faucet_account_id_bech32 = faucet_account.id().to_bech32(NetworkId::Testnet); println!("Faucet account ID: {:?}", faucet_account_id_bech32); @@ -469,7 +469,7 @@ async fn main() -> Result<(), ClientError> { let send_amount = 50; let fungible_asset = FungibleAsset::new(faucet_account.id(), send_amount).unwrap(); - let p2id_note = create_p2id_note( + let p2id_note = P2idNote::create( alice_account.id(), target_account_id, vec![fungible_asset.into()], @@ -481,9 +481,8 @@ async fn main() -> Result<(), ClientError> { } // Specifying output notes and creating a tx request to create them - let output_notes: Vec = p2id_notes.into_iter().map(OutputNote::Full).collect(); let transaction_request = TransactionRequestBuilder::new() - .own_output_notes(output_notes) + .own_output_notes(p2id_notes) .build() .unwrap(); @@ -509,7 +508,7 @@ async fn main() -> Result<(), ClientError> { let send_amount = 50; let fungible_asset = FungibleAsset::new(faucet_account.id(), send_amount).unwrap(); - let p2id_note = create_p2id_note( + let p2id_note = P2idNote::create( alice_account.id(), target_account_id, vec![fungible_asset.into()], @@ -519,7 +518,7 @@ async fn main() -> Result<(), ClientError> { )?; let transaction_request = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(p2id_note)]) + .own_output_notes(vec![p2id_note]) .build() .unwrap(); @@ -550,10 +549,10 @@ The output will look like this: Latest block: 226896 [STEP 1] Creating a new account for Alice -Alice's account ID: "mtst1qp9czj052w3hvyqqqdtxmkh4myt45x2h" +Alice's account ID: "" [STEP 2] Deploying a new fungible faucet. -Faucet account ID: "mtst1qrn8x36uckhhvgqqqdze8g6t7ggyufq0" +Faucet account ID: "" [STEP 3] Minting 5 notes of 100 tokens each for Alice. tx request built diff --git a/docs/src/rust-client/network_transactions_tutorial.md b/docs/src/rust-client/network_transactions_tutorial.md index a04ee836..af58f456 100644 --- a/docs/src/rust-client/network_transactions_tutorial.md +++ b/docs/src/rust-client/network_transactions_tutorial.md @@ -49,9 +49,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -151,22 +151,23 @@ use miden_client::{ auth::AuthSecretKey, crypto::FeltRng, builder::ClientBuilder, - keystore::FilesystemKeyStore, + keystore::{FilesystemKeyStore, Keystore}, note::{ - Note, NoteAssets, NoteInputs, NoteMetadata, NoteRecipient, NoteTag, NoteType, + NetworkAccountTarget, Note, NoteAssets, NoteError, NoteExecutionHint, NoteMetadata, + NoteRecipient, NoteStorage, NoteTag, NoteType, }, rpc::{Endpoint, GrpcClient}, - store::{AccountRecordData, TransactionFilter}, - transaction::{OutputNote, TransactionId, TransactionRequestBuilder, TransactionStatus}, + store::TransactionFilter, + transaction::{TransactionId, TransactionRequestBuilder, TransactionStatus}, Client, ClientError, Felt, Word, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; -use miden_client::auth::{self, AuthFalcon512Rpo}; +use miden_client::auth::{self, AuthSchemeId, AuthSingleSig}; use miden_client::transaction::TransactionKernel; use miden_client::{ account::{ - AccountBuilder, AccountComponent, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode, + AccountType, StorageSlot, StorageSlotName, }, assembly::{ Assembler, @@ -217,7 +218,7 @@ async fn wait_for_tx( fn create_library( account_code: String, library_path: &str, -) -> Result> { +) -> Result, Box> { let assembler: Assembler = TransactionKernel::assembler(); let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( @@ -262,13 +263,13 @@ async fn main() -> Result<(), Box> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the account let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -277,7 +278,7 @@ async fn main() -> Result<(), Box> { client.add_account(&alice_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); println!( "Alice's account ID: {:?}", @@ -314,9 +315,9 @@ let component_code = CodeBuilder::new() let counter_component = AccountComponent::new( component_code, vec![StorageSlot::with_value(counter_slot_name.clone(), [Felt::new(0); 4].into())], // Initialize counter storage to 0 + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), ) -.unwrap() -.with_supports_all_types(); +.unwrap(); // Generate a random seed for the account let mut init_seed = [0_u8; 32]; @@ -415,20 +416,25 @@ let note_script = client .with_dynamically_linked_library(&library)? .compile_note_script(&network_note_code)?; -// Create note recipient with empty inputs -let note_inputs = NoteInputs::new([].to_vec())?; -let recipient = NoteRecipient::new(serial_num, note_script, note_inputs); +// Create note recipient with empty storage +let note_storage = NoteStorage::new([].to_vec())?; +let recipient = NoteRecipient::new(serial_num, note_script, note_storage); // Set up note metadata - tag it with the counter contract ID so it gets consumed let tag = NoteTag::with_account_target(counter_contract.id()); -let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public, tag); +let attachment = NetworkAccountTarget::new(counter_contract.id(), NoteExecutionHint::Always) + .map_err(|e| NoteError::other(e.to_string()))? + .into(); +let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public) + .with_tag(tag) + .with_attachment(attachment); // Create the complete note let increment_note = Note::new(NoteAssets::default(), metadata, recipient); // Build and submit the transaction containing the note let note_req = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(increment_note)]) + .own_output_notes(vec![increment_note]) .build()?; let note_tx_id = client @@ -459,15 +465,9 @@ for _ in 0..10 { // Checking updated state let new_account_state = client.get_account(counter_contract.id()).await.unwrap(); - if let Some(account_record) = new_account_state.as_ref() { - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => { - panic!("counter contract is missing full account data") - } - }; + if let Some(account) = new_account_state.as_ref() { let count: Word = account.storage().get_item(&counter_slot_name).unwrap().into(); - let val = count.get(3).unwrap().as_int(); + let val = count[0].as_canonical_u64(); if val >= 2 { println!("πŸ”’ Final counter value: {}", val); return Ok(()); @@ -504,22 +504,23 @@ use miden_client::{ auth::AuthSecretKey, crypto::FeltRng, builder::ClientBuilder, - keystore::FilesystemKeyStore, + keystore::{FilesystemKeyStore, Keystore}, note::{ - Note, NoteAssets, NoteInputs, NoteMetadata, NoteRecipient, NoteTag, NoteType, + NetworkAccountTarget, Note, NoteAssets, NoteError, NoteExecutionHint, NoteMetadata, + NoteRecipient, NoteStorage, NoteTag, NoteType, }, rpc::{Endpoint, GrpcClient}, - store::{AccountRecordData, TransactionFilter}, - transaction::{OutputNote, TransactionId, TransactionRequestBuilder, TransactionStatus}, + store::TransactionFilter, + transaction::{TransactionId, TransactionRequestBuilder, TransactionStatus}, Client, ClientError, Felt, Word, }; use miden_client_sqlite_store::ClientBuilderSqliteExt; -use miden_client::auth::{self, AuthFalcon512Rpo}; +use miden_client::auth::{self, AuthSchemeId, AuthSingleSig}; use miden_client::transaction::TransactionKernel; use miden_client::{ account::{ - AccountBuilder, AccountComponent, AccountStorageMode, AccountType, StorageSlot, - StorageSlotName, + component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode, + AccountType, StorageSlot, StorageSlotName, }, assembly::{ Assembler, @@ -570,7 +571,7 @@ async fn wait_for_tx( fn create_library( account_code: String, library_path: &str, -) -> Result> { +) -> Result, Box> { let assembler: Assembler = TransactionKernel::assembler(); let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( @@ -615,13 +616,13 @@ async fn main() -> Result<(), Box> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Build the account let alice_account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -630,7 +631,7 @@ async fn main() -> Result<(), Box> { client.add_account(&alice_account, false).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, alice_account.id()).await.unwrap(); println!( "Alice's account ID: {:?}", @@ -654,9 +655,9 @@ async fn main() -> Result<(), Box> { let counter_component = AccountComponent::new( component_code, vec![StorageSlot::with_value(counter_slot_name.clone(), [Felt::new(0); 4].into())], // Initialize counter storage to 0 + AccountComponentMetadata::new("external_contract::counter_contract", AccountType::all()), ) - .unwrap() - .with_supports_all_types(); + .unwrap(); // Generate a random seed for the account let mut init_seed = [0_u8; 32]; @@ -736,19 +737,24 @@ async fn main() -> Result<(), Box> { .compile_note_script(&network_note_code)?; // Create note recipient with empty inputs - let note_inputs = NoteInputs::new([].to_vec())?; - let recipient = NoteRecipient::new(serial_num, note_script, note_inputs); + let note_storage = NoteStorage::new([].to_vec())?; + let recipient = NoteRecipient::new(serial_num, note_script, note_storage); // Set up note metadata - tag it with the counter contract ID so it gets consumed let tag = NoteTag::with_account_target(counter_contract.id()); - let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public, tag); + let attachment = NetworkAccountTarget::new(counter_contract.id(), NoteExecutionHint::Always) + .map_err(|e| NoteError::other(e.to_string()))? + .into(); + let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public) + .with_tag(tag) + .with_attachment(attachment); // Create the complete note let increment_note = Note::new(NoteAssets::default(), metadata, recipient); // Build and submit the transaction containing the note let note_req = TransactionRequestBuilder::new() - .own_output_notes(vec![OutputNote::Full(increment_note)]) + .own_output_notes(vec![increment_note]) .build()?; let note_tx_id = client @@ -779,15 +785,9 @@ async fn main() -> Result<(), Box> { // Checking updated state let new_account_state = client.get_account(counter_contract.id()).await.unwrap(); - if let Some(account_record) = new_account_state.as_ref() { - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => { - panic!("counter contract is missing full account data") - } - }; + if let Some(account) = new_account_state.as_ref() { let count: Word = account.storage().get_item(&counter_slot_name).unwrap().into(); - let val = count.get(3).unwrap().as_int(); + let val = count[0].as_canonical_u64(); if val >= 2 { println!("πŸ”’ Final counter value: {}", val); return Ok(()); @@ -824,22 +824,22 @@ cargo run --release --bin network_notes_counter_contract Expected output: ```text -Latest block: 508977 +Latest block: 4342 [STEP 1] Creating a new account for Alice -Alice's account ID: "mtst1qrpk3gmyv2p06ypgh7gss9hs0gl80gwl" +Alice's account ID: "mtst1azkn605dchqv7yrd9crnvrkknvw8j4d3" [STEP 2] Creating a network counter smart contract -contract id: "mtst1qz95e5k55xeh5sz2zann5xtp4uq9hpht" +contract id: "mtst1ar5dqpk49zjsvsqenfuqzskcvvmf9spc" [STEP 3] Deploy network counter smart contract -View transaction on MidenScan: https://testnet.midenscan.com/tx/0xbe8dddab0403544a28c9a24d0400837cfd639b030670cf436ba113261fbdfce0 -βœ… transaction 0xbe8dddab0403544a28c9a24d0400837cfd639b030670cf436ba113261fbdfce0 committed +View transaction on MidenScan: https://testnet.midenscan.com/tx/0xe28fa8e527335499d972e653dfd944ad591752e537a41b151e7b80d598c5660c +βœ… transaction 0xe28fa8e527335499d972e653dfd944ad591752e537a41b151e7b80d598c5660c committed [STEP 4] Creating a network note for network counter contract -View transaction on MidenScan: https://testnet.midenscan.com/tx/0x0bb5f6b786eb0f129d944975e3fae226084441eaf422f187657afbd74641327c +View transaction on MidenScan: https://testnet.midenscan.com/tx/0x3cd653f2848f2fbc3de76d7b0a92c82d23ad1f9f24c9fb86d58772534e17ee30 network increment note created, waiting for onchain commitment -βœ… transaction 0x0bb5f6b786eb0f129d944975e3fae226084441eaf422f187657afbd74641327c committed +βœ… transaction 0x3cd653f2848f2fbc3de76d7b0a92c82d23ad1f9f24c9fb86d58772534e17ee30 committed πŸ”’ Final counter value: 2 ``` diff --git a/docs/src/rust-client/oracle_tutorial.md b/docs/src/rust-client/oracle_tutorial.md index 4e4b7f4d..9b649848 100644 --- a/docs/src/rust-client/oracle_tutorial.md +++ b/docs/src/rust-client/oracle_tutorial.md @@ -37,9 +37,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -67,7 +67,6 @@ use miden_client::{ domain::account::{AccountStorageRequirements, StorageMapKey}, Endpoint, GrpcClient, }, - store::AccountRecordData, transaction::{ForeignAccount, TransactionRequestBuilder}, Client, ClientError, }; @@ -75,8 +74,8 @@ use miden_client_sqlite_store::ClientBuilderSqliteExt; use miden_client::{auth::NoAuth, transaction::TransactionKernel}; use miden_client::{ account::{ - AccountComponent, AccountId, AccountStorageMode, AccountType, StorageSlot, StorageSlotName, - StorageSlotType, + component::AccountComponentMetadata, AccountComponent, AccountId, AccountStorageMode, + AccountType, StorageSlot, StorageSlotName, StorageSlotType, }, Felt, Word, ZERO, }; @@ -93,16 +92,12 @@ pub async fn get_oracle_foreign_accounts( ) -> Result, ClientError> { client.import_account_by_id(oracle_account_id).await?; - let oracle_record = client + let oracle_account = client .get_account(oracle_account_id) .await .expect("RPC failed") .expect("oracle account not found"); - let oracle_account = match oracle_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("oracle account is missing full account data"), - }; let storage = oracle_account.storage(); let publisher_count_slot = storage .slots() @@ -117,7 +112,7 @@ pub async fn get_oracle_foreign_accounts( let publisher_count = storage .get_item(&publisher_count_slot) - .map(|word| word[0].as_int()) + .map(|word| word[0].as_canonical_u64()) .unwrap_or(0); let publisher_id_slots: Vec = storage @@ -144,17 +139,11 @@ pub async fn get_oracle_foreign_accounts( for pid in publisher_ids { client.import_account_by_id(pid).await?; - let publisher_record = client + let publisher_account = client .get_account(pid) .await .expect("RPC failed") .expect("publisher account not found"); - let publisher_account = match publisher_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => { - panic!("publisher account is missing full account data") - } - }; let map_slot_names: Vec = publisher_account .storage() .slots() @@ -184,7 +173,7 @@ fn create_library( assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), @@ -222,8 +211,11 @@ async fn main() -> Result<(), ClientError> { // ------------------------------------------------------------------------- // Get all foreign accounts for oracle data // ------------------------------------------------------------------------- - let oracle_bech32 = "mtst1qq0zffxzdykm7qqqqdt24cc2du5ghx99"; - let (_, oracle_account_id) = AccountId::from_bech32(oracle_bech32).unwrap(); + // The oracle account ID must be supplied as a CLI argument. + let oracle_bech32 = std::env::args() + .nth(1) + .expect("Usage: oracle_data_query "); + let (_, oracle_account_id) = AccountId::from_bech32(&oracle_bech32).unwrap(); let btc_usd_pair_id = 120195681; let foreign_accounts: Vec = get_oracle_foreign_accounts(&mut client, oracle_account_id, btc_usd_pair_id).await?; @@ -248,9 +240,9 @@ async fn main() -> Result<(), ClientError> { let contract_component = AccountComponent::new( contract_component_code, vec![StorageSlot::with_value(contract_slot_name.clone(), Word::default())], + AccountComponentMetadata::new("external_contract::oracle_reader", AccountType::all()), ) - .unwrap() - .with_supports_all_types(); + .unwrap(); let mut seed = [0_u8; 32]; client.rng().fill_bytes(&mut seed); @@ -312,7 +304,9 @@ _Don't run this code just yet, we still need to create our smart contract that q In the code above, we specified the Pragma oracle account id `0x4f67e78643022e00000220d8997e33` and the BTC/USD pair `120195681`. The `get_oracle_foreign_accounts` function returns all of the `ForeignAccounts` that you will need to execute the transaction to get the price data from the oracle. Since Pragma's oracle depends on multiple publishers, this function queries all of the publisher account ids required to make a successful FPI call. -To learn more about Pragma's oracle architecture, you can look at the source code here: https://github.com/astraly-labs/pragma-miden +:::note +The oracle account ID, procedure hash, and trading pair ID used in this tutorial reference Pragma's testnet deployment. These values are maintained by Pragma and may change if they redeploy their oracle. For the latest values, check the [Pragma Miden repository](https://github.com/astraly-labs/pragma-miden). +::: ## Step 2: Build the price reader smart contract and script @@ -344,7 +338,7 @@ The import `miden::tx` contains the `tx::execute_foreign_procedure` which we wil 1. Pushes `0.0.0.120195681` onto the stack, representing the BTC/USD pair in the Pragma oracle. 2. Pushes `0xb86237a8c9cd35acfef457e47282cc4da43df676df410c988eab93095d8fb3b9` onto the stack which is the procedure root of the `get_median` procedure in the oracle. -3. Pushes `599064613630720.5721796415433354752` onto the stack which is the oracle id prefix and suffix. +3. Pushes `939716883672832.2172042075194638080` onto the stack which is the oracle id prefix and suffix. 4. Calls `tx::execute_foreign_procedure` which calls the `get_median` procedure via foreign procedure invocation. Inside of the `masm/accounts/` directory, create the `oracle_reader.masm` file: @@ -433,15 +427,17 @@ View transaction on MidenScan: https://testnet.midenscan.com/tx/0xc8951190564d5c As you can see, at the top of the stack is the price returned from the Pragma oracle. The price is returned with 6 decimal places. Currently Pragma only publishes the `BTC/USD` price feed on testnet. -### Running the example +### Running the tutorial -To run the full example, navigate to the `rust-client` directory in the [miden-tutorials](https://github.com/0xMiden/miden-tutorials/) repository and run this command: +To run this tutorial end-to-end, navigate to the `rust-client` directory in the [miden-tutorials](https://github.com/0xMiden/miden-tutorials/) repository and run: ```bash cd rust-client -cargo run --release --bin oracle_data_query +cargo run --release --bin oracle_data_query -- ``` +where `` is Pragma's deployed oracle account ID on testnet. + ### Continue learning Next tutorial: [How to Use Unauthenticated Notes](./unauthenticated_note_how_to.md) diff --git a/docs/src/rust-client/public_account_interaction_tutorial.md b/docs/src/rust-client/public_account_interaction_tutorial.md index 67c2c8ed..1bdc4b1d 100644 --- a/docs/src/rust-client/public_account_interaction_tutorial.md +++ b/docs/src/rust-client/public_account_interaction_tutorial.md @@ -37,9 +37,9 @@ Add the following dependencies to your `Cargo.toml` file: ```toml [dependencies] -miden-client = { version = "0.13.0", features = ["testing", "tonic"] } -miden-client-sqlite-store = { version = "0.13.0", package = "miden-client-sqlite-store" } -miden-protocol = { version = "0.13.0" } +miden-client = { version = "0.14", features = ["testing", "tonic"] } +miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" } +miden-protocol = { version = "0.14" } rand = { version = "0.9" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } @@ -136,7 +136,6 @@ use miden_client::{ builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::TransactionRequestBuilder, ClientError, }; @@ -146,7 +145,7 @@ fn create_library( assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), @@ -201,23 +200,18 @@ println!("\n[STEP 1] Reading data from public state"); // Define the Counter Contract account id from counter contract deploy let (_, counter_contract_id) = - AccountId::from_bech32("mtst1arjemrxne8lj5qz4mg9c8mtyxg954483").unwrap(); + AccountId::from_bech32("mtst1apsd609q5966cqra992t4a00tgstrkfk").unwrap(); client .import_account_by_id(counter_contract_id) .await .unwrap(); -let counter_contract_details = client +let counter_contract = client .get_account(counter_contract_id) .await .unwrap() .expect("counter contract not found"); - -let counter_contract = match counter_contract_details.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), -}; println!( "Account details: {:?}", counter_contract.storage().slots().first().unwrap() @@ -289,15 +283,11 @@ println!( client.sync_state().await.unwrap(); // Retrieve updated contract data to see the incremented counter -let account_record = client +let account = client .get_account(counter_contract.id()) .await .unwrap() .expect("counter contract not found"); -let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), -}; let counter_slot_name = miden_client::account::StorageSlotName::new("miden::tutorials::counter") .expect("valid slot name"); @@ -327,7 +317,6 @@ use miden_client::{ builder::ClientBuilder, keystore::FilesystemKeyStore, rpc::{Endpoint, GrpcClient}, - store::AccountRecordData, transaction::TransactionRequestBuilder, ClientError, }; @@ -337,7 +326,7 @@ fn create_library( assembler: Assembler, library_path: &str, source_code: &str, -) -> Result> { +) -> Result, Box> { let source_manager = Arc::new(DefaultSourceManager::default()); let module = Module::parser(ModuleKind::Library).parse_str( AssemblyPath::new(library_path), @@ -379,23 +368,18 @@ async fn main() -> Result<(), ClientError> { // Define the Counter Contract account id from counter contract deploy let (_, counter_contract_id) = - AccountId::from_bech32("mtst1arjemrxne8lj5qz4mg9c8mtyxg954483").unwrap(); + AccountId::from_bech32("mtst1apsd609q5966cqra992t4a00tgstrkfk").unwrap(); client .import_account_by_id(counter_contract_id) .await .unwrap(); - let counter_contract_details = client + let counter_contract = client .get_account(counter_contract_id) .await .unwrap() .expect("counter contract not found"); - - let counter_contract = match counter_contract_details.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), - }; println!( "Account details: {:?}", counter_contract.storage().slots().first().unwrap() @@ -448,15 +432,11 @@ async fn main() -> Result<(), ClientError> { client.sync_state().await.unwrap(); // Retrieve updated contract data to see the incremented counter - let account_record = client + let account = client .get_account(counter_contract.id()) .await .unwrap() .expect("counter contract not found"); - let account = match account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("counter contract is missing full account data"), - }; let counter_slot_name = miden_client::account::StorageSlotName::new("miden::tutorials::counter") .expect("valid slot name"); diff --git a/docs/src/rust-client/unauthenticated_note_how_to.md b/docs/src/rust-client/unauthenticated_note_how_to.md index 02902a36..d9e3560c 100644 --- a/docs/src/rust-client/unauthenticated_note_how_to.md +++ b/docs/src/rust-client/unauthenticated_note_how_to.md @@ -53,22 +53,22 @@ Alice ➑ Bob ➑ Charlie ➑ Dave ➑ Eve ➑ Frank ➑ ... ## Full Rust code example ```rust no_run -use miden_client::auth::AuthFalcon512Rpo; +use miden_client::auth::{AuthSchemeId, AuthSingleSig}; use rand::RngCore; use std::sync::Arc; use tokio::time::{sleep, Duration, Instant}; use miden_client::{ - account::component::{BasicFungibleFaucet, BasicWallet}, + account::component::{AuthControlled, BasicFungibleFaucet, BasicWallet}, address::NetworkId, asset::{FungibleAsset, TokenSymbol}, auth::AuthSecretKey, builder::ClientBuilder, - keystore::FilesystemKeyStore, - note::{create_p2id_note, Note, NoteAttachment, NoteType}, + keystore::{FilesystemKeyStore, Keystore}, + note::{Note, NoteAttachment, NoteType, P2idNote}, rpc::{Endpoint, GrpcClient}, - store::{AccountRecordData, TransactionFilter}, - transaction::{OutputNote, TransactionId, TransactionRequestBuilder, TransactionStatus}, + store::TransactionFilter, + transaction::{TransactionId, TransactionRequestBuilder, TransactionStatus}, utils::{Deserializable, Serializable}, Client, ClientError, Felt, }; @@ -141,7 +141,7 @@ async fn main() -> Result<(), ClientError> { client.rng().fill_bytes(&mut init_seed); // Generate key pair - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); // Faucet parameters let symbol = TokenSymbol::new("MID").unwrap(); @@ -152,8 +152,9 @@ async fn main() -> Result<(), ClientError> { let faucet_account = AccountBuilder::new(init_seed) .account_type(AccountType::FungibleFaucet) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicFungibleFaucet::new(symbol, decimals, max_supply).unwrap()) + .with_component(AuthControlled::allow_all()) .build() .unwrap(); @@ -166,7 +167,7 @@ async fn main() -> Result<(), ClientError> { ); // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, faucet_account.id()).await.unwrap(); // Resync to show newly deployed faucet tokio::time::sleep(Duration::from_secs(2)).await; @@ -184,12 +185,12 @@ async fn main() -> Result<(), ClientError> { let mut init_seed = [0_u8; 32]; client.rng().fill_bytes(&mut init_seed); - let key_pair = AuthSecretKey::new_falcon512_rpo(); + let key_pair = AuthSecretKey::new_falcon512_poseidon2_with_rng(client.rng()); let account = AccountBuilder::new(init_seed) .account_type(AccountType::RegularAccountUpdatableCode) .storage_mode(AccountStorageMode::Public) - .with_auth_component(AuthFalcon512Rpo::new(key_pair.public_key().to_commitment())) + .with_auth_component(AuthSingleSig::new(key_pair.public_key().to_commitment(), AuthSchemeId::Falcon512Poseidon2)) .with_component(BasicWallet) .build() .unwrap(); @@ -203,7 +204,7 @@ async fn main() -> Result<(), ClientError> { client.add_account(&account, true).await?; // Add the key pair to the keystore - keystore.add_key(&key_pair).unwrap(); + keystore.add_key(&key_pair, account.id()).await.unwrap(); } // For demo purposes, Alice is the first account. @@ -278,7 +279,7 @@ async fn main() -> Result<(), ClientError> { NoteType::Public }; - let p2id_note = create_p2id_note( + let p2id_note = P2idNote::create( accounts[i].id(), accounts[i + 1].id(), vec![fungible_asset_send_amount.into()], @@ -288,11 +289,9 @@ async fn main() -> Result<(), ClientError> { ) .unwrap(); - let output_note = OutputNote::Full(p2id_note.clone()); - // Time transaction request building let transaction_request = TransactionRequestBuilder::new() - .own_output_notes(vec![output_note]) + .own_output_notes(vec![p2id_note.clone()]) .build() .unwrap(); @@ -336,11 +335,7 @@ async fn main() -> Result<(), ClientError> { tokio::time::sleep(Duration::from_secs(3)).await; client.sync_state().await?; for account in accounts.clone() { - let new_account_record = client.get_account(account.id()).await.unwrap().unwrap(); - let new_account = match new_account_record.account_data() { - AccountRecordData::Full(account) => account, - AccountRecordData::Partial(_) => panic!("account is missing full account data"), - }; + let new_account = client.get_account(account.id()).await.unwrap().expect("account not found"); let balance = new_account.vault().get_balance(faucet_account.id()).unwrap(); println!( "Account: {} balance: {}", @@ -359,19 +354,19 @@ The output of our program will look something like this: Latest block: 227040 [STEP 1] Deploying a new fungible faucet. -Faucet account ID: mtst1qqvhzywfzy4xugqqq0yqj28jxy3kr5hy +Faucet account ID: [STEP 2] Creating new accounts -account id 0: mtst1qrdwf5hv6wnqzyqqq06hyfvqryn2nam3 -account id 1: mtst1qz7lwv4wh27xyyqqq026adcyc54ueccz -account id 2: mtst1qzzmpa7f3tcnkyqqqdgj4dan2q8r0s6c -account id 3: mtst1qrdclj0zp3v7qyqqqdn92ad87cl0rctl -account id 4: mtst1qre79420whvn2yqqq0udf4z8d5c3xwfj -account id 5: mtst1qpmfryrdjfwazyqqqdslm7gdhur80xhk -account id 6: mtst1qr0n4cxfddn2wyqqqv2vsc9mnqh0dtyj -account id 7: mtst1qrfmw4297mchwyqqqdfzq8dl2uu89uhq -account id 8: mtst1qpevlxpnuetesyqqqdwmsgd4zua84nda -account id 9: mtst1qre7lqnwt03zwyqqqvjdlj2w6yc87u4w +account id 0: +account id 1: +account id 2: +account id 3: +account id 4: +account id 5: +account id 6: +account id 7: +account id 8: +account id 9: [STEP 3] Mint tokens Minting tokens for Alice... @@ -379,71 +374,71 @@ Minting tokens for Alice... [STEP 4] Create unauthenticated note tx chain unauthenticated tx 1 -sender: mtst1qrdwf5hv6wnqzyqqq06hyfvqryn2nam3 -target: mtst1qz7lwv4wh27xyyqqq026adcyc54ueccz +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x31f48117c645c5b4ccff78ef356bad764798d4f207925e492ebbae1b86ef4f55 Total time for loop iteration 0: 1.952243542s unauthenticated tx 2 -sender: mtst1qz7lwv4wh27xyyqqq026adcyc54ueccz -target: mtst1qzzmpa7f3tcnkyqqqdgj4dan2q8r0s6c +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x45b4c62c6e8e79a1c7200d1c84dc6304a88debd37b20b069dd739498827354c1 Total time for loop iteration 1: 2.091625458s unauthenticated tx 3 -sender: mtst1qzzmpa7f3tcnkyqqqdgj4dan2q8r0s6c -target: mtst1qrdclj0zp3v7qyqqqdn92ad87cl0rctl +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0xb2241e10df8f6f891b910975a3b4f4fd47657c47de164138300d683cfca5dd61 Total time for loop iteration 2: 1.846021291s unauthenticated tx 4 -sender: mtst1qrdclj0zp3v7qyqqqdn92ad87cl0rctl -target: mtst1qre79420whvn2yqqq0udf4z8d5c3xwfj +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0xd3ea6fa1da6c317f055ac4b069388d93b88d526039e01531879e75598e0f8cff Total time for loop iteration 3: 1.877627958s unauthenticated tx 5 -sender: mtst1qre79420whvn2yqqq0udf4z8d5c3xwfj -target: mtst1qpmfryrdjfwazyqqqdslm7gdhur80xhk +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x6098638ec0ff7331432c037331ee7372977abe20af5c56315985fd314e21548d Total time for loop iteration 4: 1.884586875s unauthenticated tx 6 -sender: mtst1qpmfryrdjfwazyqqqdslm7gdhur80xhk -target: mtst1qr0n4cxfddn2wyqqqv2vsc9mnqh0dtyj +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x8258292e49e0cfdd96603450c2de6738afecb1e7482ede0fb68ea375e884e1d8 Total time for loop iteration 5: 1.886505875s unauthenticated tx 7 -sender: mtst1qr0n4cxfddn2wyqqqv2vsc9mnqh0dtyj -target: mtst1qrfmw4297mchwyqqqdfzq8dl2uu89uhq +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0x9e0f84e00a9393bf6e5f224d55ccdf8bd0ef32ee20c3299e2dfccf1771001dfd Total time for loop iteration 6: 2.095149458s unauthenticated tx 8 -sender: mtst1qrfmw4297mchwyqqqdfzq8dl2uu89uhq -target: mtst1qpevlxpnuetesyqqqdwmsgd4zua84nda +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0xa9db6445dfaa44ccf9dd52bf4cd8d9057946571ccb5299a7a56c59faf2ed2093 Total time for loop iteration 7: 1.935587291s unauthenticated tx 9 -sender: mtst1qpevlxpnuetesyqqqdwmsgd4zua84nda -target: mtst1qre7lqnwt03zwyqqqvjdlj2w6yc87u4w +sender: +target: Consumed Note Tx on MidenScan: https://testnet.midenscan.com/tx/0xba4bb4ae3c7aaf949cdd3be8c9ea52169f958e7dca8e9d4541fd5ac939393e41 Total time for loop iteration 8: 1.964682833s Total execution time for unauthenticated note txs: 17.534611542s blocks: [BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047), BlockNumber(227047)] -Account: mtst1qrdwf5hv6wnqzyqqq06hyfvqryn2nam3 balance: 80 -Account: mtst1qz7lwv4wh27xyyqqq026adcyc54ueccz balance: 0 -Account: mtst1qzzmpa7f3tcnkyqqqdgj4dan2q8r0s6c balance: 0 -Account: mtst1qrdclj0zp3v7qyqqqdn92ad87cl0rctl balance: 0 -Account: mtst1qre79420whvn2yqqq0udf4z8d5c3xwfj balance: 0 -Account: mtst1qpmfryrdjfwazyqqqdslm7gdhur80xhk balance: 0 -Account: mtst1qr0n4cxfddn2wyqqqv2vsc9mnqh0dtyj balance: 0 -Account: mtst1qrfmw4297mchwyqqqdfzq8dl2uu89uhq balance: 0 -Account: mtst1qpevlxpnuetesyqqqdwmsgd4zua84nda balance: 0 -Account: mtst1qre7lqnwt03zwyqqqvjdlj2w6yc87u4w balance: 20 +Account: balance: 80 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 0 +Account: balance: 20 ``` ## Conclusion diff --git a/docs/src/web-client/counter_contract_tutorial.md b/docs/src/web-client/counter_contract_tutorial.md index 6b12c9f7..7b52d0d9 100644 --- a/docs/src/web-client/counter_contract_tutorial.md +++ b/docs/src/web-client/counter_contract_tutorial.md @@ -3,18 +3,18 @@ title: 'Incrementing the Count of the Counter Contract' sidebar_position: 5 --- -_Using the Miden WebClient to interact with a custom smart contract_ +_Using the Miden client to interact with a custom smart contract_ ## Overview -In this tutorial, we will interact with a counter contract already deployed on chain by incrementing the count using the Miden WebClient. +In this tutorial, we will deploy a custom counter smart contract and increment its count using the Miden client. Each run creates a fresh counter account, deploys it to the network, and immediately calls its `increment_count` procedure via a transaction script β€” so the final count is always `1`. -Using a script, we will invoke the increment function within the counter contract to update the count. This tutorial provides a foundational understanding of interacting with custom smart contracts on Miden. +This tutorial provides a foundational understanding of building and interacting with custom smart contracts on Miden. ## What we'll cover -- Interacting with a custom smart contract on Miden -- Calling procedures in an account from a script +- Deploying a custom smart contract on Miden from a web client +- Calling procedures in an account from a transaction script ## Prerequisites @@ -40,9 +40,9 @@ This tutorial assumes you have a basic understanding of Miden assembly. To quick cd miden-web-app ``` -3. Install the Miden WebClient SDK: +3. Install the Miden SDK: ```bash - yarn add @miden-sdk/miden-sdk@0.13.0 + yarn add @miden-sdk/miden-sdk@0.14.4 ``` **NOTE!**: Be sure to add the `--webpack` command to your `package.json` when running the `dev script`. The dev script should look like this: @@ -78,7 +78,9 @@ export default function Home() {

Miden Web App

-

Open your browser console to see WebClient logs.

+

+ Open your browser console to see Miden client logs. +

+ ); +} +``` + +:::warning Types imported from `/lazy` are stubs until `ready()` resolves + +Never construct wasm-bindgen types (`AccountId`, `Note`, `createP2IDNote`, `TransactionRequestBuilder`, etc.) at module top level or in a render-body `useMemo` β€” always inside an effect, event handler, or async hook callback where WASM is already initialized. For display-only cases like shortening an address, slice the bech32 string directly (`addr.slice(0, 8) + '…' + addr.slice(-4)`); don't parse it with `AccountId.fromBech32()` just to get a prefix. + +::: + +## Node.js 22+ `localStorage` polyfill + +If you run `next dev` under Node.js 22 or later, every page request will crash with: + +``` +TypeError: localStorage.getItem is not a function +``` + +This is a Node + Next.js interaction, not a Miden SDK issue. Node 22+ defines `globalThis.localStorage` as an object, but its methods (`getItem`, `setItem`, …) are undefined unless Node is launched with `--localstorage-file`. Next.js's dev overlay guards with `typeof localStorage !== 'undefined'`, which passes on Node 22+, and then calls the missing methods. + +Add this polyfill at the top of `next.config.ts`, before the config object: + +```ts +{ + const store = new Map(); + const poly = { + getItem: (key: string) => store.get(key) ?? null, + setItem: (key: string, value: string) => { + store.set(key, value); + }, + removeItem: (key: string) => { + store.delete(key); + }, + clear: () => { + store.clear(); + }, + get length() { + return store.size; + }, + key: (index: number) => [...store.keys()][index] ?? null, + }; + (globalThis as Record).localStorage = poly; +} +``` + +This only affects `next dev` (SSR); static exports via `next build` are unaffected. The polyfill is harmless on Node ≀21 β€” it installs an in-memory stub that the dev overlay uses just like Node 22+'s (broken) built-in. + +## SDK API Patterns + +### Transaction return types + +All transaction methods return an object, not a plain transaction ID: + +```ts +// mint and consume return { txId, result } +const { txId } = await client.transactions.mint({ ... }); + +// send returns { txId, note, result } +// note is non-null when returnNote: true +const { txId, note } = await client.transactions.send({ + ..., + returnNote: true, +}); +``` + +### Waiting for confirmation + +You can wait for a transaction to be committed in two ways: + +```ts +// Option 1: Pass waitForConfirmation in the transaction call +await client.transactions.mint({ + ..., + waitForConfirmation: true, +}); + +// Option 2: Wait separately using waitFor +const { txId } = await client.transactions.mint({ ... }); +await client.transactions.waitFor(txId); // accepts TransactionId object or hex string +``` + +### Using transaction IDs in URLs + +When displaying transaction IDs in explorer links, call `.toHex()`: + +```ts +const { txId } = await client.transactions.mint({ ... }); +console.log(`https://testnet.midenscan.com/tx/${txId.toHex()}`); +``` + +### Authentication + +Create an authentication key using `AuthSecretKey` (inside an async function, after awaiting `MidenClient.ready()` so the wasm-bindgen constructor is live): + +```ts +import { MidenClient, AuthSecretKey } from '@miden-sdk/miden-sdk/lazy'; + +export async function createAuth() { + await MidenClient.ready(); + + const seed = new Uint8Array(32); + crypto.getRandomValues(seed); + const auth = AuthSecretKey.rpoFalconWithRNG(seed); + return { seed, auth }; +} +``` + +Pass `auth` and `seed` when creating contract accounts that require authentication. + +### Concurrency safety and `waitForIdle()` + +As of `@miden-sdk/miden-sdk@0.14.4`, all mutating `WebClient` methods (`transactions.execute`, `transactions.submit`, `syncState`, account creation) and async proxy-fallback reads (`getAccount`, `importAccountById`, `getAccountStorage`, etc.) are internally serialized through a single promise chain. Consumers no longer need to maintain their own JS-level mutex, and the `"recursive use of an object detected"` wasm-bindgen panic caused by the 15-second auto-sync timer racing with user operations is gone. + +For the rare case where you need to coordinate a non-WASM side effect (for example, clearing an in-memory auth key on wallet lock) with whatever SDK work is currently in flight, drain the queue first: + +```ts +await client.waitForIdle(); // resolves when every serialized call has settled +clearMyAuthKeys(); +``` diff --git a/docs/src/web-client/unauthenticated_note_how_to.md b/docs/src/web-client/unauthenticated_note_how_to.md index 83fee2f6..c59210c3 100644 --- a/docs/src/web-client/unauthenticated_note_how_to.md +++ b/docs/src/web-client/unauthenticated_note_how_to.md @@ -5,11 +5,11 @@ sidebar_position: 6 import { CodeSdkTabs } from '@site/src/components'; -_Using unauthenticated notes for optimistic note consumption with the Miden WebClient_ +_Using unauthenticated notes for optimistic note consumption with the Miden client_ ## Overview -In this tutorial, we will explore how to leverage unauthenticated notes on Miden to settle transactions faster than the blocktime using the Miden WebClient. Unauthenticated notes are essentially UTXOs that have not yet been fully committed into a block. This feature allows the notes to be created and consumed within the same batch during [batch production](https://0xmiden.github.io/miden-docs/imported/miden-base/src/blockchain.html#batch-production). +In this tutorial, we will explore how to leverage unauthenticated notes on Miden to settle transactions faster than the blocktime using the Miden client. Unauthenticated notes are essentially UTXOs that have not yet been fully committed into a block. This feature allows the notes to be created and consumed within the same batch during [batch production](https://0xmiden.github.io/miden-docs/imported/miden-base/src/blockchain.html#batch-production). When using unauthenticated notes, both the creation and consumption of notes can happen within the same batch, enabling faster-than-blocktime settlement. This is particularly powerful for applications requiring high-frequency transactions or optimistic settlement patterns. @@ -24,7 +24,7 @@ Alice ➑ Wallet 1 ➑ Wallet 2 ➑ Wallet 3 ➑ Wallet 4 ➑ Wallet 5 ## What we'll cover - **Introduction to Unauthenticated Notes:** Understand what unauthenticated notes are and how they differ from standard notes. -- **WebClient Setup:** Configure the Miden WebClient for browser-based transactions. +- **Miden Client Setup:** Configure the Miden client for browser-based transactions. - **P2ID Note Creation:** Learn how to create Pay-to-ID notes for targeted transfers. - **Performance Insights:** Observe how unauthenticated notes can reduce transaction times dramatically. @@ -40,12 +40,10 @@ This tutorial assumes you have a basic understanding of Miden assembly. To quick 1. **Next.js Project Setup:** - Create a new Next.js application with TypeScript. - - Install the Miden WebClient SDK. + - Install the Miden SDK. -2. **WebClient Initialization:** - - Set up the WebClient to connect with the Miden testnet. - -- Configure a local prover for improved performance. +2. **Client Initialization:** + - Set up the Miden client to connect with the Miden testnet. 3. **Account Creation:** - Create wallet accounts for Alice and multiple transfer recipients. @@ -79,8 +77,8 @@ This tutorial assumes you have a basic understanding of Miden assembly. To quick 3. Install the Miden SDK: **NOTE!**: Be sure to add the `--webpack` command to your `package.json` when running the `dev script`. The dev script should look like this: @@ -131,7 +129,9 @@ export default function Home() {

Miden Web App

-

Open your browser console to see WebClient logs.

+

+ Open your browser console to see Miden client logs. +