diff --git a/.github/workflows/ci-generate-ci.yml b/.github/workflows/ci-generate-ci.yml index 17fc90db937..1ecf196331e 100644 --- a/.github/workflows/ci-generate-ci.yml +++ b/.github/workflows/ci-generate-ci.yml @@ -47,10 +47,11 @@ jobs: if [ -n "$(git status --porcelain)" ]; then git config --global user.name "IDX GitHub Automation" - git config --global user.email "IDX GitHub Automation" + git config --global user.email "idx@dfinity.org" git add . git commit -m "IDX GitHub Automation" git push + exit 1 else echo "git working tree clean - no changes to be committed" fi diff --git a/Cargo.Bazel.Fuzzing.json.lock b/Cargo.Bazel.Fuzzing.json.lock index bcbb23035a8..08fd98a11dc 100644 --- a/Cargo.Bazel.Fuzzing.json.lock +++ b/Cargo.Bazel.Fuzzing.json.lock @@ -1,5 +1,5 @@ { - "checksum": "8fd8fccec5a57eefbac6e6bc61cde6077b347dc896dd713bf649cb70bb4778b1", + "checksum": "befed3db2258ef5e97774c44951feb5c8ca098af84913123d4a8945afeac827c", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -11122,19 +11122,19 @@ "target": "crossterm" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "crossterm 0.27.0", "target": "crossterm" @@ -11268,6 +11268,16 @@ "target": "wasm_bindgen" } ], + "wasm32-wasip1": [ + { + "id": "serde-wasm-bindgen 0.5.0", + "target": "serde_wasm_bindgen" + }, + { + "id": "wasm-bindgen 0.2.95", + "target": "wasm_bindgen" + } + ], "x86_64-apple-darwin": [ { "id": "crossterm 0.27.0", @@ -11280,25 +11290,25 @@ "target": "crossterm" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "crossterm 0.27.0", "target": "crossterm" @@ -11761,12 +11771,6 @@ "target": "iana_time_zone" } ], - "aarch64-fuchsia": [ - { - "id": "iana-time-zone 0.1.59", - "target": "iana_time_zone" - } - ], "aarch64-linux-android": [ { "id": "android-tzdata 0.1.1", @@ -11783,6 +11787,12 @@ "target": "windows_targets" } ], + "aarch64-unknown-fuchsia": [ + { + "id": "iana-time-zone 0.1.59", + "target": "iana_time_zone" + } + ], "aarch64-unknown-linux-gnu": [ { "id": "iana-time-zone 0.1.59", @@ -11891,12 +11901,6 @@ "target": "iana_time_zone" } ], - "x86_64-fuchsia": [ - { - "id": "iana-time-zone 0.1.59", - "target": "iana_time_zone" - } - ], "x86_64-linux-android": [ { "id": "android-tzdata 0.1.1", @@ -11919,6 +11923,12 @@ "target": "iana_time_zone" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "iana-time-zone 0.1.59", + "target": "iana_time_zone" + } + ], "x86_64-unknown-linux-gnu": [ { "id": "iana-time-zone 0.1.59", @@ -15758,7 +15768,7 @@ "target": "signal_hook_mio" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "mio 0.8.10", "target": "mio" @@ -15772,7 +15782,17 @@ "target": "signal_hook_mio" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ + { + "id": "crossterm_winapi 0.9.1", + "target": "crossterm_winapi" + }, + { + "id": "winapi 0.3.9", + "target": "winapi" + } + ], + "aarch64-unknown-fuchsia": [ { "id": "mio 0.8.10", "target": "mio" @@ -15786,16 +15806,6 @@ "target": "signal_hook_mio" } ], - "aarch64-pc-windows-msvc": [ - { - "id": "crossterm_winapi 0.9.1", - "target": "crossterm_winapi" - }, - { - "id": "winapi 0.3.9", - "target": "winapi" - } - ], "aarch64-unknown-linux-gnu": [ { "id": "mio 0.8.10", @@ -16008,7 +16018,7 @@ "target": "signal_hook_mio" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "mio 0.8.10", "target": "mio" @@ -16022,7 +16032,17 @@ "target": "signal_hook_mio" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ + { + "id": "crossterm_winapi 0.9.1", + "target": "crossterm_winapi" + }, + { + "id": "winapi 0.3.9", + "target": "winapi" + } + ], + "x86_64-unknown-freebsd": [ { "id": "mio 0.8.10", "target": "mio" @@ -16036,17 +16056,7 @@ "target": "signal_hook_mio" } ], - "x86_64-pc-windows-msvc": [ - { - "id": "crossterm_winapi 0.9.1", - "target": "crossterm_winapi" - }, - { - "id": "winapi 0.3.9", - "target": "winapi" - } - ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "mio 0.8.10", "target": "mio" @@ -22607,19 +22617,19 @@ "target": "parking" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "parking 2.1.1", "target": "parking" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "parking 2.1.1", "target": "parking" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "parking 2.1.1", "target": "parking" @@ -22739,25 +22749,25 @@ "target": "parking" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "parking 2.1.1", "target": "parking" @@ -22860,19 +22870,19 @@ "target": "parking" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "parking 2.1.1", "target": "parking" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "parking 2.1.1", "target": "parking" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "parking 2.1.1", "target": "parking" @@ -22992,25 +23002,25 @@ "target": "parking" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "parking 2.1.1", "target": "parking" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "parking 2.1.1", "target": "parking" @@ -29105,15 +29115,15 @@ "webpki-roots", "webpki-tokio" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "webpki-roots", "webpki-tokio" ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ "webpki-roots", "webpki-tokio" ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ "webpki-roots", "webpki-tokio" ], @@ -29193,10 +29203,6 @@ "webpki-roots", "webpki-tokio" ], - "x86_64-fuchsia": [ - "webpki-roots", - "webpki-tokio" - ], "x86_64-linux-android": [ "webpki-roots", "webpki-tokio" @@ -29209,6 +29215,10 @@ "webpki-roots", "webpki-tokio" ], + "x86_64-unknown-fuchsia": [ + "webpki-roots", + "webpki-tokio" + ], "x86_64-unknown-linux-gnu": [ "webpki-roots", "webpki-tokio" @@ -29290,19 +29300,19 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" @@ -29422,25 +29432,25 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" @@ -33041,7 +33051,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid 1.5.0": { @@ -33113,7 +33125,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid_transform 1.5.0": { @@ -33189,7 +33203,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid_transform_data 1.5.0": { @@ -33225,7 +33241,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_normalizer 1.5.0": { @@ -33318,7 +33336,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_normalizer_data 1.5.0": { @@ -33354,7 +33374,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_properties 1.5.1": { @@ -33435,7 +33457,9 @@ "version": "1.5.1" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_properties_data 1.5.0": { @@ -33471,7 +33495,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_provider 1.5.0": { @@ -33559,7 +33585,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_provider_macros 1.5.0": { @@ -33612,7 +33640,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "id-arena 2.2.1": { @@ -39107,7 +39137,9 @@ "version": "0.7.3" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "little-loadshedder 0.2.0": { @@ -41709,10 +41741,10 @@ "aarch64-apple-ios-sim": [ "os-ext" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "os-ext" ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ "os-ext" ], "aarch64-unknown-linux-gnu": [ @@ -41757,15 +41789,15 @@ "x86_64-apple-ios": [ "os-ext" ], - "x86_64-fuchsia": [ - "os-ext" - ], "x86_64-linux-android": [ "os-ext" ], "x86_64-unknown-freebsd": [ "os-ext" ], + "x86_64-unknown-fuchsia": [ + "os-ext" + ], "x86_64-unknown-linux-gnu": [ "os-ext" ], @@ -53715,13 +53747,13 @@ "target": "libc" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -53811,19 +53843,19 @@ "target": "libc" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -56068,7 +56100,7 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56098,7 +56130,7 @@ "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56128,7 +56160,7 @@ "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56804,7 +56836,7 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56834,7 +56866,7 @@ "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56864,7 +56896,7 @@ "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -56894,7 +56926,7 @@ "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "async-compression 0.4.4", "target": "async_compression" @@ -57278,7 +57310,7 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -57328,7 +57360,7 @@ "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -57378,7 +57410,7 @@ "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58360,6 +58392,12 @@ "target": "wasm_streams" } ], + "wasm32-wasip1": [ + { + "id": "wasm-streams 0.4.0", + "target": "wasm_streams" + } + ], "x86_64-apple-darwin": [ { "id": "futures-channel 0.3.31", @@ -58460,7 +58498,7 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58510,7 +58548,7 @@ "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58560,7 +58598,7 @@ "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58610,7 +58648,7 @@ "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -60728,7 +60766,7 @@ "time", "use-libc-auxv" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "default", "event", "mm", @@ -60738,7 +60776,7 @@ "time", "use-libc-auxv" ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ "default", "event", "mm", @@ -60914,6 +60952,11 @@ "termios", "use-libc-auxv" ], + "wasm32-wasip1": [ + "default", + "termios", + "use-libc-auxv" + ], "x86_64-apple-darwin": [ "default", "event", @@ -60934,7 +60977,7 @@ "time", "use-libc-auxv" ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ "default", "event", "mm", @@ -60944,7 +60987,7 @@ "time", "use-libc-auxv" ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ "default", "event", "mm", @@ -60954,7 +60997,7 @@ "time", "use-libc-auxv" ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ "default", "event", "mm", @@ -61042,7 +61085,7 @@ "target": "libc" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "errno 0.3.8", "target": "errno", @@ -61053,22 +61096,22 @@ "target": "libc" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "errno 0.3.8", "target": "errno", "alias": "libc_errno" - }, - { - "id": "libc 0.2.158", - "target": "libc" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "errno 0.3.8", "target": "errno", "alias": "libc_errno" + }, + { + "id": "libc 0.2.158", + "target": "libc" } ], "aarch64-unknown-nto-qnx710": [ @@ -61255,7 +61298,7 @@ "target": "libc" } ], - "x86_64-apple-darwin": [ + "wasm32-wasip1": [ { "id": "errno 0.3.8", "target": "errno", @@ -61266,7 +61309,7 @@ "target": "libc" } ], - "x86_64-apple-ios": [ + "x86_64-apple-darwin": [ { "id": "errno 0.3.8", "target": "errno", @@ -61277,7 +61320,7 @@ "target": "libc" } ], - "x86_64-fuchsia": [ + "x86_64-apple-ios": [ { "id": "errno 0.3.8", "target": "errno", @@ -61317,6 +61360,17 @@ "target": "libc" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "errno 0.3.8", + "target": "errno", + "alias": "libc_errno" + }, + { + "id": "libc 0.2.158", + "target": "libc" + } + ], "x86_64-unknown-none": [ { "id": "errno 0.3.8", @@ -67814,15 +67868,15 @@ "aarch64-apple-ios-sim": [ "once" ], - "aarch64-fuchsia": [ - "once" - ], "aarch64-linux-android": [ "once" ], "aarch64-pc-windows-msvc": [ "once" ], + "aarch64-unknown-fuchsia": [ + "once" + ], "aarch64-unknown-linux-gnu": [ "once" ], @@ -67868,9 +67922,6 @@ "x86_64-apple-ios": [ "once" ], - "x86_64-fuchsia": [ - "once" - ], "x86_64-linux-android": [ "once" ], @@ -67880,6 +67931,9 @@ "x86_64-unknown-freebsd": [ "once" ], + "x86_64-unknown-fuchsia": [ + "once" + ], "x86_64-unknown-linux-gnu": [ "once" ], @@ -70030,13 +70084,13 @@ "target": "xattr" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "xattr 0.2.3", "target": "xattr" @@ -70132,19 +70186,19 @@ "target": "xattr" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "xattr 0.2.3", "target": "xattr" @@ -71828,7 +71882,7 @@ "target": "num_threads" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -71838,7 +71892,7 @@ "target": "num_threads" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -71988,7 +72042,7 @@ "target": "num_threads" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -71998,7 +72052,7 @@ "target": "num_threads" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" @@ -72008,7 +72062,7 @@ "target": "num_threads" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -72336,7 +72390,9 @@ "version": "0.7.6" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "tinytemplate 1.2.1": { @@ -72719,7 +72775,7 @@ "target": "socket2" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -72733,7 +72789,17 @@ "target": "socket2" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ + { + "id": "socket2 0.5.7", + "target": "socket2" + }, + { + "id": "windows-sys 0.52.0", + "target": "windows_sys" + } + ], + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -72747,16 +72813,6 @@ "target": "socket2" } ], - "aarch64-pc-windows-msvc": [ - { - "id": "socket2 0.5.7", - "target": "socket2" - }, - { - "id": "windows-sys 0.52.0", - "target": "windows_sys" - } - ], "aarch64-unknown-linux-gnu": [ { "id": "libc 0.2.158", @@ -72993,7 +73049,7 @@ "target": "socket2" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -73007,7 +73063,17 @@ "target": "socket2" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ + { + "id": "socket2 0.5.7", + "target": "socket2" + }, + { + "id": "windows-sys 0.52.0", + "target": "windows_sys" + } + ], + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" @@ -73021,17 +73087,7 @@ "target": "socket2" } ], - "x86_64-pc-windows-msvc": [ - { - "id": "socket2 0.5.7", - "target": "socket2" - }, - { - "id": "windows-sys 0.52.0", - "target": "windows_sys" - } - ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -79939,12 +79995,6 @@ "target": "rustix" } ], - "aarch64-fuchsia": [ - { - "id": "rustix 0.38.32", - "target": "rustix" - } - ], "aarch64-linux-android": [ { "id": "rustix 0.38.32", @@ -79957,6 +80007,12 @@ "target": "windows_sys" } ], + "aarch64-unknown-fuchsia": [ + { + "id": "rustix 0.38.32", + "target": "rustix" + } + ], "aarch64-unknown-linux-gnu": [ { "id": "memfd 0.6.4", @@ -80087,12 +80143,6 @@ "target": "rustix" } ], - "x86_64-fuchsia": [ - { - "id": "rustix 0.38.32", - "target": "rustix" - } - ], "x86_64-linux-android": [ { "id": "rustix 0.38.32", @@ -80111,6 +80161,12 @@ "target": "rustix" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "rustix 0.38.32", + "target": "rustix" + } + ], "x86_64-unknown-linux-gnu": [ { "id": "memfd 0.6.4", @@ -84734,7 +84790,9 @@ "version": "0.5.5" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "wsl 0.1.0": { @@ -85397,7 +85455,9 @@ "version": "0.7.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "yoke-derive 0.7.4": { @@ -85454,7 +85514,9 @@ "version": "0.7.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerocopy 0.7.32": { @@ -85620,7 +85682,9 @@ "version": "0.1.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerofrom-derive 0.1.4": { @@ -85677,7 +85741,9 @@ "version": "0.1.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zeroize 1.8.1": { @@ -85855,7 +85921,9 @@ "version": "0.10.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerovec-derive 0.10.3": { @@ -85908,7 +85976,9 @@ "version": "0.10.3" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zstd 0.13.2": { @@ -86166,9 +86236,6 @@ "aarch64-apple-ios-sim": [ "aarch64-apple-ios-sim" ], - "aarch64-fuchsia": [ - "aarch64-fuchsia" - ], "aarch64-linux-android": [ "aarch64-linux-android" ], @@ -86176,6 +86243,9 @@ "aarch64-pc-windows-msvc": [ "aarch64-pc-windows-msvc" ], + "aarch64-unknown-fuchsia": [ + "aarch64-unknown-fuchsia" + ], "aarch64-unknown-linux-gnu": [ "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu" @@ -86218,10 +86288,10 @@ "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86239,8 +86309,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-nto-qnx710", "armv7-linux-androideabi", "i686-apple-darwin", @@ -86254,11 +86324,12 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-none" ], "cfg(all(target_arch = \"aarch64\", target_env = \"msvc\", not(windows_raw_dylib)))": [ @@ -86283,7 +86354,8 @@ "wasm32-unknown-unknown" ], "cfg(all(target_arch = \"wasm32\", target_os = \"wasi\"))": [ - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(all(target_arch = \"wasm32\", target_vendor = \"unknown\", target_os = \"unknown\", target_env = \"\"))": [ "wasm32-unknown-unknown" @@ -86311,8 +86383,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86327,14 +86399,14 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], "cfg(all(unix, not(target_os = \"android\"), not(target_vendor = \"apple\"), not(target_arch = \"wasm32\")))": [ - "aarch64-fuchsia", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86344,16 +86416,16 @@ "i686-unknown-linux-gnu", "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", - "x86_64-fuchsia", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], "cfg(all(unix, not(target_os = \"macos\")))": [ "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86366,9 +86438,9 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86377,9 +86449,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86395,10 +86467,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86407,9 +86479,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86420,10 +86492,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86432,9 +86504,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86445,10 +86517,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86465,17 +86537,17 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" ], "cfg(any(target_arch = \"x86\", target_arch = \"x86_64\", all(any(target_arch = \"aarch64\", target_arch = \"arm\"), any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))))": [ - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "arm-unknown-linux-gnueabi", @@ -86488,10 +86560,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86504,10 +86576,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86550,9 +86622,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "arm-unknown-linux-gnueabi", @@ -86566,12 +86638,13 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86625,8 +86698,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86641,9 +86714,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86651,8 +86724,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86667,9 +86740,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86677,8 +86750,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86692,11 +86765,12 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86704,9 +86778,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86722,10 +86796,10 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86734,9 +86808,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86754,12 +86828,13 @@ "s390x-unknown-linux-gnu", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86768,8 +86843,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86788,18 +86863,19 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" ], "cfg(not(any(target_os = \"macos\", target_os = \"ios\", target_os = \"windows\", target_arch = \"wasm32\")))": [ - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86815,9 +86891,9 @@ "s390x-unknown-linux-gnu", "thumbv7em-none-eabi", "thumbv8m.main-none-eabi", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86826,8 +86902,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86846,9 +86922,9 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86857,8 +86933,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86876,11 +86952,12 @@ "thumbv7em-none-eabi", "thumbv8m.main-none-eabi", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86889,9 +86966,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86911,10 +86988,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86923,9 +87000,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86945,10 +87022,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86957,8 +87034,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86977,11 +87054,12 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86990,9 +87068,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -87012,12 +87090,13 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -87027,16 +87106,17 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710" ], "cfg(target_arch = \"wasm32\")": [ "wasm32-unknown-unknown", - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(target_arch = \"x86\")": [ "i686-apple-darwin", @@ -87048,10 +87128,10 @@ "cfg(target_arch = \"x86_64\")": [ "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -87072,8 +87152,8 @@ "cfg(target_os = \"cloudabi\")": [], "cfg(target_os = \"dragonfly\")": [], "cfg(target_os = \"fuchsia\")": [ - "aarch64-fuchsia", - "x86_64-fuchsia" + "aarch64-unknown-fuchsia", + "x86_64-unknown-fuchsia" ], "cfg(target_os = \"haiku\")": [], "cfg(target_os = \"hermit\")": [], @@ -87100,7 +87180,8 @@ ], "cfg(target_os = \"redox\")": [], "cfg(target_os = \"wasi\")": [ - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(target_os = \"windows\")": [ "aarch64-pc-windows-msvc", @@ -87112,8 +87193,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -87128,9 +87209,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -87182,15 +87263,15 @@ "wasm32-wasi": [ "wasm32-wasi" ], + "wasm32-wasip1": [ + "wasm32-wasip1" + ], "x86_64-apple-darwin": [ "x86_64-apple-darwin" ], "x86_64-apple-ios": [ "x86_64-apple-ios" ], - "x86_64-fuchsia": [ - "x86_64-fuchsia" - ], "x86_64-linux-android": [ "x86_64-linux-android" ], @@ -87202,6 +87283,9 @@ "x86_64-unknown-freebsd": [ "x86_64-unknown-freebsd" ], + "x86_64-unknown-fuchsia": [ + "x86_64-unknown-fuchsia" + ], "x86_64-unknown-linux-gnu": [ "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" diff --git a/Cargo.Bazel.json.lock b/Cargo.Bazel.json.lock index d5c0c188242..b5e8dae02b1 100644 --- a/Cargo.Bazel.json.lock +++ b/Cargo.Bazel.json.lock @@ -1,5 +1,5 @@ { - "checksum": "194342fc37fdddbf3dceb1e96cdf4ce10a63ff4ec17867d1a241e3e034c1ad0c", + "checksum": "16c350a57ca08666035e4f0e31f17c9715860d84ed6755b026870a84de503a09", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -11018,19 +11018,19 @@ "target": "crossterm" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "crossterm 0.27.0", "target": "crossterm" @@ -11164,6 +11164,16 @@ "target": "wasm_bindgen" } ], + "wasm32-wasip1": [ + { + "id": "serde-wasm-bindgen 0.5.0", + "target": "serde_wasm_bindgen" + }, + { + "id": "wasm-bindgen 0.2.95", + "target": "wasm_bindgen" + } + ], "x86_64-apple-darwin": [ { "id": "crossterm 0.27.0", @@ -11176,25 +11186,25 @@ "target": "crossterm" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "crossterm 0.27.0", "target": "crossterm" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "crossterm 0.27.0", "target": "crossterm" @@ -11657,12 +11667,6 @@ "target": "iana_time_zone" } ], - "aarch64-fuchsia": [ - { - "id": "iana-time-zone 0.1.59", - "target": "iana_time_zone" - } - ], "aarch64-linux-android": [ { "id": "android-tzdata 0.1.1", @@ -11679,6 +11683,12 @@ "target": "windows_targets" } ], + "aarch64-unknown-fuchsia": [ + { + "id": "iana-time-zone 0.1.59", + "target": "iana_time_zone" + } + ], "aarch64-unknown-linux-gnu": [ { "id": "iana-time-zone 0.1.59", @@ -11787,12 +11797,6 @@ "target": "iana_time_zone" } ], - "x86_64-fuchsia": [ - { - "id": "iana-time-zone 0.1.59", - "target": "iana_time_zone" - } - ], "x86_64-linux-android": [ { "id": "android-tzdata 0.1.1", @@ -11815,6 +11819,12 @@ "target": "iana_time_zone" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "iana-time-zone 0.1.59", + "target": "iana_time_zone" + } + ], "x86_64-unknown-linux-gnu": [ { "id": "iana-time-zone 0.1.59", @@ -15586,7 +15596,7 @@ "target": "signal_hook_mio" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "mio 0.8.10", "target": "mio" @@ -15600,7 +15610,17 @@ "target": "signal_hook_mio" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ + { + "id": "crossterm_winapi 0.9.1", + "target": "crossterm_winapi" + }, + { + "id": "winapi 0.3.9", + "target": "winapi" + } + ], + "aarch64-unknown-fuchsia": [ { "id": "mio 0.8.10", "target": "mio" @@ -15614,16 +15634,6 @@ "target": "signal_hook_mio" } ], - "aarch64-pc-windows-msvc": [ - { - "id": "crossterm_winapi 0.9.1", - "target": "crossterm_winapi" - }, - { - "id": "winapi 0.3.9", - "target": "winapi" - } - ], "aarch64-unknown-linux-gnu": [ { "id": "mio 0.8.10", @@ -15836,7 +15846,7 @@ "target": "signal_hook_mio" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "mio 0.8.10", "target": "mio" @@ -15850,7 +15860,17 @@ "target": "signal_hook_mio" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ + { + "id": "crossterm_winapi 0.9.1", + "target": "crossterm_winapi" + }, + { + "id": "winapi 0.3.9", + "target": "winapi" + } + ], + "x86_64-unknown-freebsd": [ { "id": "mio 0.8.10", "target": "mio" @@ -15864,17 +15884,7 @@ "target": "signal_hook_mio" } ], - "x86_64-pc-windows-msvc": [ - { - "id": "crossterm_winapi 0.9.1", - "target": "crossterm_winapi" - }, - { - "id": "winapi 0.3.9", - "target": "winapi" - } - ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "mio 0.8.10", "target": "mio" @@ -22458,19 +22468,19 @@ "target": "parking" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "parking 2.1.0", "target": "parking" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "parking 2.1.0", "target": "parking" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "parking 2.1.0", "target": "parking" @@ -22590,25 +22600,25 @@ "target": "parking" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "parking 2.1.0", "target": "parking" @@ -22711,19 +22721,19 @@ "target": "parking" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "parking 2.1.0", "target": "parking" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "parking 2.1.0", "target": "parking" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "parking 2.1.0", "target": "parking" @@ -22843,25 +22853,25 @@ "target": "parking" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "parking 2.1.0", "target": "parking" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "parking 2.1.0", "target": "parking" @@ -28960,15 +28970,15 @@ "webpki-roots", "webpki-tokio" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "webpki-roots", "webpki-tokio" ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ "webpki-roots", "webpki-tokio" ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ "webpki-roots", "webpki-tokio" ], @@ -29048,10 +29058,6 @@ "webpki-roots", "webpki-tokio" ], - "x86_64-fuchsia": [ - "webpki-roots", - "webpki-tokio" - ], "x86_64-linux-android": [ "webpki-roots", "webpki-tokio" @@ -29064,6 +29070,10 @@ "webpki-roots", "webpki-tokio" ], + "x86_64-unknown-fuchsia": [ + "webpki-roots", + "webpki-tokio" + ], "x86_64-unknown-linux-gnu": [ "webpki-roots", "webpki-tokio" @@ -29145,19 +29155,19 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" @@ -29277,25 +29287,25 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "webpki-roots 0.26.1", "target": "webpki_roots" @@ -32875,7 +32885,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid 1.5.0": { @@ -32947,7 +32959,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid_transform 1.5.0": { @@ -33023,7 +33037,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_locid_transform_data 1.5.0": { @@ -33059,7 +33075,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_normalizer 1.5.0": { @@ -33152,7 +33170,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_normalizer_data 1.5.0": { @@ -33188,7 +33208,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_properties 1.5.1": { @@ -33269,7 +33291,9 @@ "version": "1.5.1" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_properties_data 1.5.0": { @@ -33305,7 +33329,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_provider 1.5.0": { @@ -33393,7 +33419,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "icu_provider_macros 1.5.0": { @@ -33446,7 +33474,9 @@ "version": "1.5.0" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "id-arena 2.2.1": { @@ -38944,7 +38974,9 @@ "version": "0.7.3" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "little-loadshedder 0.2.0": { @@ -41549,10 +41581,10 @@ "aarch64-apple-ios-sim": [ "os-ext" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "os-ext" ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ "os-ext" ], "aarch64-unknown-linux-gnu": [ @@ -41597,15 +41629,15 @@ "x86_64-apple-ios": [ "os-ext" ], - "x86_64-fuchsia": [ - "os-ext" - ], "x86_64-linux-android": [ "os-ext" ], "x86_64-unknown-freebsd": [ "os-ext" ], + "x86_64-unknown-fuchsia": [ + "os-ext" + ], "x86_64-unknown-linux-gnu": [ "os-ext" ], @@ -53517,13 +53549,13 @@ "target": "libc" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -53613,19 +53645,19 @@ "target": "libc" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -55914,7 +55946,7 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -55944,7 +55976,7 @@ "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -55974,7 +56006,7 @@ "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -56650,7 +56682,7 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -56680,7 +56712,7 @@ "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -56710,7 +56742,7 @@ "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -56740,7 +56772,7 @@ "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "async-compression 0.4.3", "target": "async_compression" @@ -57124,7 +57156,7 @@ "target": "webpki_roots" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -57174,7 +57206,7 @@ "target": "webpki_roots" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -57224,7 +57256,7 @@ "target": "webpki_roots" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58206,6 +58238,12 @@ "target": "wasm_streams" } ], + "wasm32-wasip1": [ + { + "id": "wasm-streams 0.4.0", + "target": "wasm_streams" + } + ], "x86_64-apple-darwin": [ { "id": "futures-channel 0.3.31", @@ -58306,7 +58344,7 @@ "target": "webpki_roots" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58356,7 +58394,7 @@ "target": "webpki_roots" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58406,7 +58444,7 @@ "target": "webpki_roots" } ], - "x86_64-pc-windows-msvc": [ + "x86_64-unknown-freebsd": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -58456,7 +58494,7 @@ "target": "webpki_roots" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "futures-channel 0.3.31", "target": "futures_channel" @@ -60574,7 +60612,7 @@ "time", "use-libc-auxv" ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ "default", "event", "mm", @@ -60584,7 +60622,7 @@ "time", "use-libc-auxv" ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ "default", "event", "mm", @@ -60760,6 +60798,11 @@ "termios", "use-libc-auxv" ], + "wasm32-wasip1": [ + "default", + "termios", + "use-libc-auxv" + ], "x86_64-apple-darwin": [ "default", "event", @@ -60780,7 +60823,7 @@ "time", "use-libc-auxv" ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ "default", "event", "mm", @@ -60790,7 +60833,7 @@ "time", "use-libc-auxv" ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ "default", "event", "mm", @@ -60800,7 +60843,7 @@ "time", "use-libc-auxv" ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ "default", "event", "mm", @@ -60888,7 +60931,7 @@ "target": "libc" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "errno 0.3.8", "target": "errno", @@ -60899,22 +60942,22 @@ "target": "libc" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ { "id": "errno 0.3.8", "target": "errno", "alias": "libc_errno" - }, - { - "id": "libc 0.2.158", - "target": "libc" } ], - "aarch64-pc-windows-msvc": [ + "aarch64-unknown-fuchsia": [ { "id": "errno 0.3.8", "target": "errno", "alias": "libc_errno" + }, + { + "id": "libc 0.2.158", + "target": "libc" } ], "aarch64-unknown-nto-qnx710": [ @@ -61101,7 +61144,7 @@ "target": "libc" } ], - "x86_64-apple-darwin": [ + "wasm32-wasip1": [ { "id": "errno 0.3.8", "target": "errno", @@ -61112,7 +61155,7 @@ "target": "libc" } ], - "x86_64-apple-ios": [ + "x86_64-apple-darwin": [ { "id": "errno 0.3.8", "target": "errno", @@ -61123,7 +61166,7 @@ "target": "libc" } ], - "x86_64-fuchsia": [ + "x86_64-apple-ios": [ { "id": "errno 0.3.8", "target": "errno", @@ -61163,6 +61206,17 @@ "target": "libc" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "errno 0.3.8", + "target": "errno", + "alias": "libc_errno" + }, + { + "id": "libc 0.2.158", + "target": "libc" + } + ], "x86_64-unknown-none": [ { "id": "errno 0.3.8", @@ -67660,15 +67714,15 @@ "aarch64-apple-ios-sim": [ "once" ], - "aarch64-fuchsia": [ - "once" - ], "aarch64-linux-android": [ "once" ], "aarch64-pc-windows-msvc": [ "once" ], + "aarch64-unknown-fuchsia": [ + "once" + ], "aarch64-unknown-linux-gnu": [ "once" ], @@ -67714,9 +67768,6 @@ "x86_64-apple-ios": [ "once" ], - "x86_64-fuchsia": [ - "once" - ], "x86_64-linux-android": [ "once" ], @@ -67726,6 +67777,9 @@ "x86_64-unknown-freebsd": [ "once" ], + "x86_64-unknown-fuchsia": [ + "once" + ], "x86_64-unknown-linux-gnu": [ "once" ], @@ -69876,13 +69930,13 @@ "target": "xattr" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "xattr 0.2.3", "target": "xattr" @@ -69978,19 +70032,19 @@ "target": "xattr" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "xattr 0.2.3", "target": "xattr" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "xattr 0.2.3", "target": "xattr" @@ -71674,7 +71728,7 @@ "target": "num_threads" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -71684,7 +71738,7 @@ "target": "num_threads" } ], - "aarch64-linux-android": [ + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -71834,7 +71888,7 @@ "target": "num_threads" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -71844,7 +71898,7 @@ "target": "num_threads" } ], - "x86_64-linux-android": [ + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" @@ -71854,7 +71908,7 @@ "target": "num_threads" } ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -72182,7 +72236,9 @@ "version": "0.7.6" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "tinytemplate 1.2.1": { @@ -72565,7 +72621,7 @@ "target": "socket2" } ], - "aarch64-fuchsia": [ + "aarch64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -72579,7 +72635,17 @@ "target": "socket2" } ], - "aarch64-linux-android": [ + "aarch64-pc-windows-msvc": [ + { + "id": "socket2 0.5.7", + "target": "socket2" + }, + { + "id": "windows-sys 0.52.0", + "target": "windows_sys" + } + ], + "aarch64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -72593,16 +72659,6 @@ "target": "socket2" } ], - "aarch64-pc-windows-msvc": [ - { - "id": "socket2 0.5.7", - "target": "socket2" - }, - { - "id": "windows-sys 0.52.0", - "target": "windows_sys" - } - ], "aarch64-unknown-linux-gnu": [ { "id": "libc 0.2.158", @@ -72839,7 +72895,7 @@ "target": "socket2" } ], - "x86_64-fuchsia": [ + "x86_64-linux-android": [ { "id": "libc 0.2.158", "target": "libc" @@ -72853,7 +72909,17 @@ "target": "socket2" } ], - "x86_64-linux-android": [ + "x86_64-pc-windows-msvc": [ + { + "id": "socket2 0.5.7", + "target": "socket2" + }, + { + "id": "windows-sys 0.52.0", + "target": "windows_sys" + } + ], + "x86_64-unknown-freebsd": [ { "id": "libc 0.2.158", "target": "libc" @@ -72867,17 +72933,7 @@ "target": "socket2" } ], - "x86_64-pc-windows-msvc": [ - { - "id": "socket2 0.5.7", - "target": "socket2" - }, - { - "id": "windows-sys 0.52.0", - "target": "windows_sys" - } - ], - "x86_64-unknown-freebsd": [ + "x86_64-unknown-fuchsia": [ { "id": "libc 0.2.158", "target": "libc" @@ -79785,12 +79841,6 @@ "target": "rustix" } ], - "aarch64-fuchsia": [ - { - "id": "rustix 0.38.32", - "target": "rustix" - } - ], "aarch64-linux-android": [ { "id": "rustix 0.38.32", @@ -79803,6 +79853,12 @@ "target": "windows_sys" } ], + "aarch64-unknown-fuchsia": [ + { + "id": "rustix 0.38.32", + "target": "rustix" + } + ], "aarch64-unknown-linux-gnu": [ { "id": "memfd 0.6.4", @@ -79933,12 +79989,6 @@ "target": "rustix" } ], - "x86_64-fuchsia": [ - { - "id": "rustix 0.38.32", - "target": "rustix" - } - ], "x86_64-linux-android": [ { "id": "rustix 0.38.32", @@ -79957,6 +80007,12 @@ "target": "rustix" } ], + "x86_64-unknown-fuchsia": [ + { + "id": "rustix 0.38.32", + "target": "rustix" + } + ], "x86_64-unknown-linux-gnu": [ { "id": "memfd 0.6.4", @@ -84554,7 +84610,9 @@ "version": "0.5.5" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "wsl 0.1.0": { @@ -85217,7 +85275,9 @@ "version": "0.7.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "yoke-derive 0.7.4": { @@ -85274,7 +85334,9 @@ "version": "0.7.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerocopy 0.7.32": { @@ -85440,7 +85502,9 @@ "version": "0.1.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerofrom-derive 0.1.4": { @@ -85497,7 +85561,9 @@ "version": "0.1.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zeroize 1.8.1": { @@ -85675,7 +85741,9 @@ "version": "0.10.4" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zerovec-derive 0.10.3": { @@ -85728,7 +85796,9 @@ "version": "0.10.3" }, "license": "Unicode-3.0", - "license_ids": [], + "license_ids": [ + "Unicode-3.0" + ], "license_file": "LICENSE" }, "zstd 0.12.4": { @@ -86124,9 +86194,6 @@ "aarch64-apple-ios-sim": [ "aarch64-apple-ios-sim" ], - "aarch64-fuchsia": [ - "aarch64-fuchsia" - ], "aarch64-linux-android": [ "aarch64-linux-android" ], @@ -86134,6 +86201,9 @@ "aarch64-pc-windows-msvc": [ "aarch64-pc-windows-msvc" ], + "aarch64-unknown-fuchsia": [ + "aarch64-unknown-fuchsia" + ], "aarch64-unknown-linux-gnu": [ "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu" @@ -86176,10 +86246,10 @@ "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86197,8 +86267,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-nto-qnx710", "armv7-linux-androideabi", "i686-apple-darwin", @@ -86212,11 +86282,12 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-none" ], "cfg(all(target_arch = \"aarch64\", target_env = \"msvc\", not(windows_raw_dylib)))": [ @@ -86241,7 +86312,8 @@ "wasm32-unknown-unknown" ], "cfg(all(target_arch = \"wasm32\", target_os = \"wasi\"))": [ - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(all(target_arch = \"wasm32\", target_vendor = \"unknown\", target_os = \"unknown\", target_env = \"\"))": [ "wasm32-unknown-unknown" @@ -86269,8 +86341,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86285,14 +86357,14 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], "cfg(all(unix, not(target_os = \"android\"), not(target_vendor = \"apple\"), not(target_arch = \"wasm32\")))": [ - "aarch64-fuchsia", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86302,16 +86374,16 @@ "i686-unknown-linux-gnu", "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", - "x86_64-fuchsia", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], "cfg(all(unix, not(target_os = \"macos\")))": [ "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86324,9 +86396,9 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86335,9 +86407,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86353,10 +86425,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86365,9 +86437,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86378,10 +86450,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86390,9 +86462,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86403,10 +86475,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86416,8 +86488,8 @@ "s390x-unknown-linux-gnu" ], "cfg(any(target_arch = \"x86\", target_arch = \"x86_64\", all(any(target_arch = \"aarch64\", target_arch = \"arm\"), any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))))": [ - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "arm-unknown-linux-gnueabi", @@ -86430,10 +86502,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86446,10 +86518,10 @@ "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86492,9 +86564,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "arm-unknown-linux-gnueabi", @@ -86508,12 +86580,13 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86567,8 +86640,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86583,9 +86656,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86593,8 +86666,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86609,9 +86682,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86619,8 +86692,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86634,11 +86707,12 @@ "powerpc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -86647,9 +86721,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86667,19 +86741,20 @@ "s390x-unknown-linux-gnu", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" ], "cfg(not(any(target_os = \"macos\", target_os = \"ios\", target_os = \"windows\", target_arch = \"wasm32\")))": [ - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86695,9 +86770,9 @@ "s390x-unknown-linux-gnu", "thumbv7em-none-eabi", "thumbv8m.main-none-eabi", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86706,8 +86781,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86726,9 +86801,9 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86737,8 +86812,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86756,11 +86831,12 @@ "thumbv7em-none-eabi", "thumbv8m.main-none-eabi", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86769,9 +86845,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86791,10 +86867,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86803,9 +86879,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86825,10 +86901,10 @@ "thumbv8m.main-none-eabi", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86837,8 +86913,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86857,11 +86933,12 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86870,9 +86947,9 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -86892,12 +86969,13 @@ "thumbv8m.main-none-eabi", "wasm32-unknown-unknown", "wasm32-wasi", + "wasm32-wasip1", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86907,16 +86985,17 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710" ], "cfg(target_arch = \"wasm32\")": [ "wasm32-unknown-unknown", - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(target_arch = \"x86\")": [ "i686-apple-darwin", @@ -86928,10 +87007,10 @@ "cfg(target_arch = \"x86_64\")": [ "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu", "x86_64-unknown-none" @@ -86952,8 +87031,8 @@ "cfg(target_os = \"cloudabi\")": [], "cfg(target_os = \"dragonfly\")": [], "cfg(target_os = \"fuchsia\")": [ - "aarch64-fuchsia", - "x86_64-fuchsia" + "aarch64-unknown-fuchsia", + "x86_64-unknown-fuchsia" ], "cfg(target_os = \"haiku\")": [], "cfg(target_os = \"hermit\")": [], @@ -86980,7 +87059,8 @@ ], "cfg(target_os = \"redox\")": [], "cfg(target_os = \"wasi\")": [ - "wasm32-wasi" + "wasm32-wasi", + "wasm32-wasip1" ], "cfg(target_os = \"windows\")": [ "aarch64-pc-windows-msvc", @@ -86992,8 +87072,8 @@ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-sim", - "aarch64-fuchsia", "aarch64-linux-android", + "aarch64-unknown-fuchsia", "aarch64-unknown-linux-gnu", "aarch64-unknown-nixos-gnu", "aarch64-unknown-nto-qnx710", @@ -87008,9 +87088,9 @@ "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-apple-ios", - "x86_64-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" ], @@ -87062,15 +87142,15 @@ "wasm32-wasi": [ "wasm32-wasi" ], + "wasm32-wasip1": [ + "wasm32-wasip1" + ], "x86_64-apple-darwin": [ "x86_64-apple-darwin" ], "x86_64-apple-ios": [ "x86_64-apple-ios" ], - "x86_64-fuchsia": [ - "x86_64-fuchsia" - ], "x86_64-linux-android": [ "x86_64-linux-android" ], @@ -87082,6 +87162,9 @@ "x86_64-unknown-freebsd": [ "x86_64-unknown-freebsd" ], + "x86_64-unknown-fuchsia": [ + "x86_64-unknown-fuchsia" + ], "x86_64-unknown-linux-gnu": [ "x86_64-unknown-linux-gnu", "x86_64-unknown-nixos-gnu" diff --git a/Cargo.lock b/Cargo.lock index 909606d2516..1e410db98ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13318,6 +13318,7 @@ version = "0.9.0" dependencies = [ "ic-types", "lru", + "proptest", ] [[package]] @@ -17124,6 +17125,7 @@ version = "6.0.0" dependencies = [ "backoff", "base64 0.13.1", + "bitcoin 0.28.2", "candid", "candid_parser", "ed25519-dalek", @@ -18428,6 +18430,28 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "release-runscript" +version = "0.9.0" +dependencies = [ + "anyhow", + "candid", + "colored", + "futures", + "ic-agent", + "ic-base-types", + "ic-nervous-system-agent", + "ic-nervous-system-clients", + "ic-nervous-system-common-test-keys", + "ic-nns-common", + "ic-nns-constants", + "rgb", + "serde", + "serde_json", + "tempfile", + "tokio", +] + [[package]] name = "rend" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index 521019dae7b..de382d1e46c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,6 +197,7 @@ members = [ "rs/nervous_system/runtime", "rs/nervous_system/string", "rs/nervous_system/temporary", + "rs/nervous_system/tools/release-runscript", "rs/nervous_system/tools/sync-with-released-nervous-system-wasms", "rs/nns/constants", "rs/nns/common", diff --git a/MODULE.bazel b/MODULE.bazel index 12ba3cb1a37..d0e9fbe3a2d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -518,6 +518,15 @@ http_file( url = "https://github.com/dfinity/sdk/raw/0.14.2/src/distributed/assetstorage.wasm.gz", ) +# Asset canister that certifies long assets chunk-wise + +http_file( + name = "long_asset_canister", + downloaded_file_path = "http_gateway_canister_custom_assets.wasm.gz", + sha256 = "eedcbf986c67fd4ebe3042094604a9a5703e825e56433e2509a6a4d0384ccf95", + url = "https://github.com/dfinity/http-gateway/raw/refs/heads/main/examples/http-gateway/canister/http_gateway_canister_custom_assets.wasm.gz", +) + # Old version of wallet canister http_file( @@ -854,8 +863,8 @@ http_file( http_file( name = "management_canister_did", downloaded_file_path = "ic.did", - sha256 = "31d4654d60b364420a2e52f546f06b2255dc78ac8c2d768271f004b8946e92cb", - url = "https://raw.githubusercontent.com/dfinity/portal/407ec5b92d06618c4df9f52e98514c5f4f44313e/docs/references/_attachments/ic.did", + sha256 = "0e92d8b9c2cf3d3fca166b76b2d3b8a2464d9b2b61117d8b2f63222b388d8dd1", + url = "https://raw.githubusercontent.com/dfinity/portal/78c93aa37ef17dc67484079d1a4bf58a10a63106/docs/references/_attachments/ic.did", ) # Mozilla CA certificate store in PEM format diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 09c62d8bd34..10c29ef4de2 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -96,11 +96,8 @@ sol_register_toolchains( http_archive( name = "rules_rust", - # Back-ported fix: https://github.com/bazelbuild/rules_rust/pull/2981 - patch_args = ["-p1"], - patches = ["//bazel:rules_rust.patch"], - sha256 = "85e2013727ab26fb22abdffe4b2ac0c27a2d5b6296167ba63d8f6e13140f51f9", - urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.53.0/rules_rust-v0.53.0.tar.gz"], + sha256 = "af4f56caae50a99a68bfce39b141b509dd68548c8204b98ab7a1cafc94d5bb02", + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.54.1/rules_rust-v0.54.1.tar.gz"], ) load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") diff --git a/bazel/rules_rust.patch b/bazel/rules_rust.patch deleted file mode 100644 index d9252428a0b..00000000000 --- a/bazel/rules_rust.patch +++ /dev/null @@ -1,45 +0,0 @@ -# Backports for https://github.com/bazelbuild/rules_rust/issues/2974 and https://github.com/bazelbuild/rules_rust/pull/2981 -diff --git a/cargo/cargo_build_script_runner/bin.rs b/cargo/cargo_build_script_runner/bin.rs -index 2dab3578..b5bb4fca 100644 ---- a/cargo/cargo_build_script_runner/bin.rs -+++ b/cargo/cargo_build_script_runner/bin.rs -@@ -187,9 +187,9 @@ fn run_buildrs() -> Result<(), String> { - .as_bytes(), - ) - .unwrap_or_else(|_| panic!("Unable to write file {:?}", output_dep_env_path)); -- write(&stdout_path, process_output.stdout) -+ write(&stdout_path, "") - .unwrap_or_else(|_| panic!("Unable to write file {:?}", stdout_path)); -- write(&stderr_path, process_output.stderr) -+ write(&stderr_path, "") - .unwrap_or_else(|_| panic!("Unable to write file {:?}", stderr_path)); - - let CompileAndLinkFlags { -diff --git a/crate_universe/private/crate.bzl b/crate_universe/private/crate.bzl -index c493e9a6..ad317abf 100644 ---- a/crate_universe/private/crate.bzl -+++ b/crate_universe/private/crate.bzl -@@ -230,7 +230,22 @@ def _stringify_label(value): - def _stringify_list(values): - if not values: - return values -- return [str(x) for x in values] -+ -+ if type(values) == "list": -+ return [str(x) for x in values] -+ -+ -+ -+ -+ if type(values) == "struct" and type(values.selects) != "NoneType": -+ new_selects = {} -+ -+ for k, v in values.selects.items(): -+ new_selects[k] = [str(x) for x in values.selects[k]] -+ -+ return struct(common = [str(x) for x in values.common], selects = new_selects) -+ -+ fail("Cannot stringify unknown type for list '{}'".format(values)) - - def _select(common, selects): - """A Starlark Select for `crate.annotation()`. diff --git a/bazel/sanitizers_enabled_env/defs.bzl b/bazel/sanitizers_enabled_env/defs.bzl index 091354e0076..a6e65bef9a2 100644 --- a/bazel/sanitizers_enabled_env/defs.bzl +++ b/bazel/sanitizers_enabled_env/defs.bzl @@ -8,7 +8,7 @@ def _impl(repository_ctx): ) repository_ctx.file( "defs.bzl", - content = "SANITIZERS_ENABLED=" + repository_ctx.os.environ.get("SANITIZERS_ENABLED", "0") + "\n", + content = "SANITIZERS_ENABLED=" + repository_ctx.getenv("SANITIZERS_ENABLED", "0") + "\n", executable = False, ) @@ -16,6 +16,5 @@ def sanitizers_enabled_env(name = None): rule = repository_rule( implementation = _impl, local = True, - environ = ["SANITIZERS_ENABLED"], ) rule(name = name) diff --git a/mainnet-canister-revisions.json b/mainnet-canister-revisions.json index f940ecf64b1..f9d79c4935f 100644 --- a/mainnet-canister-revisions.json +++ b/mainnet-canister-revisions.json @@ -44,16 +44,16 @@ "sha256": "98a7b7391608dc4a554d6964bad24157b6aaf890a05bbaad3fcc92033d9c7b02" }, "cycles-minting": { - "rev": "ee52ab3056cf5f39b09b08de70bdd20485c8b2dc", - "sha256": "bbb8995cb749ba9e2c721ff507f5e5313f32e69b1adf3df20e3901ed56a70b42" + "rev": "b5192581ccd35b67fe5a1f795ead9cbcd25956d6", + "sha256": "11c8dedd11741f05990498c90f925e9e37ad60647a65ef47caa59cdba234be6f" }, "genesis-token": { "rev": "4bed17bfc82cddc5691743db6228992cdc2740f4", "sha256": "fd25a4e2e283b498c3be1aaf63cc9b2726264d78a12b12f43ad453ceeb575e7c" }, "governance": { - "rev": "ee52ab3056cf5f39b09b08de70bdd20485c8b2dc", - "sha256": "a23918c2c5d1302e5d1149f557b0fb913ab65931c1bce3ffc94a48e3d14ecbac" + "rev": "b5192581ccd35b67fe5a1f795ead9cbcd25956d6", + "sha256": "5b67e1d273afb691a74ff29e0a495fb2ce7ee31196af58d801a8ce86a7dc4320" }, "index": { "rev": "7c6309cb5bec7ab28ed657ac7672af08a59fc1ba", @@ -64,16 +64,16 @@ "sha256": "a9ed1cb9dda555e0fc1038825eb7b3a6b366f17aa4b88575184c7537e864e551" }, "lifeline": { - "rev": "a0207146be211cdff83321c99e9e70baa62733c7", - "sha256": "76978515223287ece643bc7ca087eb310412b737e2382a73b8ae55fcb458da5b" + "rev": "b5192581ccd35b67fe5a1f795ead9cbcd25956d6", + "sha256": "8c8eb285de53ca5609abd7dc41ba3ec8eeb67708b81469311fd670e6738d7d0a" }, "registry": { - "rev": "86229594d61b433c39fc5331ab818ccb6c6aa6a7", - "sha256": "b0b2a7f37e76fcbab20a861fdf65c34d7ac2ca84a5190d204dfe5e1c50fb383e" + "rev": "b5192581ccd35b67fe5a1f795ead9cbcd25956d6", + "sha256": "771041412d2af4eb681262ca525bce1a87c199b631e17b55e1d7f9abb2cde3e6" }, "root": { - "rev": "c494c2af8bfc70a6501448dc73bf806477388738", - "sha256": "657010591182ce758c86f020d1eade5f7a188072cf0de9c41e2f9d577849c964" + "rev": "b5192581ccd35b67fe5a1f795ead9cbcd25956d6", + "sha256": "d3c702648ca4fb232f349bad7533c400c474a528abf62c05d4b100b4cdb91ce2" }, "sns-wasm": { "rev": "25c1bb0227d9970f5673b908817d7c4962b29911", @@ -84,8 +84,8 @@ "sha256": "f94cf1db965b7042197e5894fef54f5f413bb2ebc607ff0fb59c9d4dfd3babea" }, "sns_governance": { - "rev": "25c1bb0227d9970f5673b908817d7c4962b29911", - "sha256": "51fd3d1a529f3f7bad808b19074e761ce3538282ac8189bd7067b4156360c279" + "rev": "df7d443e6219c462b305152b63ca265171feb6ee", + "sha256": "bd936ef6bb878df87856a0b0c46034a242a88b7f1eeff5439daf6278febca6b7" }, "sns_index": { "rev": "2190613d3b5bcd9b74c382b22d151580b8ac271a", diff --git a/mainnet-subnet-revisions.json b/mainnet-subnet-revisions.json index c29b115e706..2c5e960f9d8 100644 --- a/mainnet-subnet-revisions.json +++ b/mainnet-subnet-revisions.json @@ -1,6 +1,6 @@ { "subnets": { - "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe": "d69648b2f5a3d90fb515824314ac2f868cbf499a", - "io67a-2jmkw-zup3h-snbwi-g6a5n-rm5dn-b6png-lvdpl-nqnto-yih6l-gqe": "43670245ed6919790e7858813c7e838c6fbcedf5" + "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe": "43670245ed6919790e7858813c7e838c6fbcedf5", + "io67a-2jmkw-zup3h-snbwi-g6a5n-rm5dn-b6png-lvdpl-nqnto-yih6l-gqe": "aa705aaa621c2e0d4f146f3a1de801edcb0fa0d5" } } \ No newline at end of file diff --git a/packages/pocket-ic/BUILD.bazel b/packages/pocket-ic/BUILD.bazel index 56cbb3fed7e..57e445d9270 100644 --- a/packages/pocket-ic/BUILD.bazel +++ b/packages/pocket-ic/BUILD.bazel @@ -33,6 +33,7 @@ MACRO_DEPENDENCIES = [ TEST_DEPENDENCIES = [ # Keep sorted. "//rs/types/error_types", + "@crate_index//:bitcoin", "@crate_index//:candid_parser", "@crate_index//:ed25519-dalek", "@crate_index//:flate2", diff --git a/packages/pocket-ic/Cargo.toml b/packages/pocket-ic/Cargo.toml index 01e3ad0f479..fbf1a1555bf 100644 --- a/packages/pocket-ic/Cargo.toml +++ b/packages/pocket-ic/Cargo.toml @@ -46,6 +46,7 @@ tracing-subscriber = { workspace = true } wslpath = "0.0.2" [dev-dependencies] +bitcoin = { workspace = true } candid_parser = { workspace = true } ed25519-dalek = { workspace = true } flate2 = { workspace = true } diff --git a/packages/pocket-ic/src/management_canister.rs b/packages/pocket-ic/src/management_canister.rs index 1878e6728e2..e76660c5237 100644 --- a/packages/pocket-ic/src/management_canister.rs +++ b/packages/pocket-ic/src/management_canister.rs @@ -1,6 +1,7 @@ use candid::{CandidType, Deserialize, Principal}; pub type CanisterId = Principal; +pub type SubnetId = Principal; #[derive(CandidType, Deserialize, Debug, Clone)] pub struct CanisterIdRecord { @@ -234,6 +235,11 @@ pub struct CanisterInfoArgs { pub num_requested_changes: Option, } +#[derive(CandidType, Deserialize, Debug, Clone)] +pub struct SubnetInfoArgs { + pub subnet_id: SubnetId, +} + #[derive(CandidType, Deserialize, Debug, Clone)] pub enum ChangeOrigin { #[serde(rename = "from_user")] @@ -292,6 +298,11 @@ pub struct CanisterInfoResult { pub total_num_changes: u64, } +#[derive(CandidType, Deserialize, Debug, Clone)] +pub struct SubnetInfoResult { + pub replica_version: String, +} + // raw randomness pub type RawRandResult = Vec; @@ -455,6 +466,18 @@ pub struct SignWithSchnorrArgs { pub key_id: SignWithSchnorrArgsKeyId, pub derivation_path: Vec>, pub message: Vec, + pub aux: Option, +} + +#[derive(CandidType, Deserialize, Debug, Clone)] +pub enum SignWithSchnorrAux { + #[serde(rename = "bip341")] + Bip341(SignWithBip341Aux), +} + +#[derive(CandidType, Deserialize, Debug, Clone)] +pub struct SignWithBip341Aux { + pub merkle_root_hash: Vec, } #[derive(CandidType, Deserialize, Debug, Clone)] diff --git a/packages/pocket-ic/test_canister/src/canister.rs b/packages/pocket-ic/test_canister/src/canister.rs index 53cd4ffad6c..8f8fe0b6a2d 100644 --- a/packages/pocket-ic/test_canister/src/canister.rs +++ b/packages/pocket-ic/test_canister/src/canister.rs @@ -109,6 +109,18 @@ struct SignWithSchnorrArgument { pub message: Vec, pub derivation_path: Vec>, pub key_id: SchnorrKeyId, + pub aux: Option, +} + +#[derive(CandidType, Serialize, Deserialize, Debug)] +pub enum SignWithSchnorrAux { + #[serde(rename = "bip341")] + Bip341(SignWithBip341Aux), +} + +#[derive(CandidType, Serialize, Deserialize, Debug)] +pub struct SignWithBip341Aux { + pub merkle_root_hash: ByteBuf, } #[derive(CandidType, Deserialize, Debug)] @@ -144,11 +156,13 @@ async fn sign_with_schnorr( message: Vec, derivation_path: Vec>, key_id: SchnorrKeyId, + aux: Option, ) -> Result, String> { let internal_request = SignWithSchnorrArgument { message, derivation_path, key_id, + aux, }; let (internal_reply,): (SignWithSchnorrResponse,) = ic_cdk::api::call::call_with_payment( diff --git a/packages/pocket-ic/tests/management_canister.rs b/packages/pocket-ic/tests/management_canister.rs index b6e813729eb..fe1c68e261e 100644 --- a/packages/pocket-ic/tests/management_canister.rs +++ b/packages/pocket-ic/tests/management_canister.rs @@ -61,6 +61,11 @@ fn canister_info(_: CanisterInfoArgs) -> CanisterInfoResult { unreachable!() } +#[update] +fn subnet_info(_: SubnetInfoArgs) -> SubnetInfoResult { + unreachable!() +} + #[update] fn delete_canister(_: CanisterIdRecord) { unreachable!() diff --git a/packages/pocket-ic/tests/tests.rs b/packages/pocket-ic/tests/tests.rs index 295ed91d115..196a11777e1 100644 --- a/packages/pocket-ic/tests/tests.rs +++ b/packages/pocket-ic/tests/tests.rs @@ -5,7 +5,7 @@ use ic_transport_types::EnvelopeContent::ReadState; use pocket_ic::management_canister::{ CanisterId, CanisterIdRecord, CanisterInstallMode, CanisterSettings, EcdsaPublicKeyResult, HttpRequestResult, ProvisionalCreateCanisterWithCyclesArgs, SchnorrAlgorithm, - SchnorrPublicKeyArgsKeyId, SchnorrPublicKeyResult, + SchnorrPublicKeyArgsKeyId, SchnorrPublicKeyResult, SignWithBip341Aux, SignWithSchnorrAux, }; use pocket_ic::{ common::rest::{ @@ -946,53 +946,96 @@ fn test_schnorr() { // We define the message, derivation path, and ECDSA key ID to use in this test. let message = b"Hello, world!==================="; // must be of length 32 bytes for BIP340 let derivation_path = vec!["my message".as_bytes().to_vec()]; + let some_aux: Option = + Some(SignWithSchnorrAux::Bip341(SignWithBip341Aux { + merkle_root_hash: b"Hello, aux!=====================".to_vec(), + })); for algorithm in [SchnorrAlgorithm::Bip340Secp256K1, SchnorrAlgorithm::Ed25519] { for name in ["key_1", "test_key_1", "dfx_test_key"] { - let key_id = SchnorrPublicKeyArgsKeyId { - algorithm: algorithm.clone(), - name: name.to_string(), - }; - - // We get the Schnorr public key and signature via update calls to the test canister. - let schnorr_public_key = update_candid::< - (Option, _, _), - (Result,), - >( - &pic, - canister, - "schnorr_public_key", - (None, derivation_path.clone(), key_id.clone()), - ) - .unwrap() - .0 - .unwrap(); - let schnorr_signature = update_candid::<_, (Result, String>,)>( - &pic, - canister, - "sign_with_schnorr", - (message, derivation_path.clone(), key_id.clone()), - ) - .unwrap() - .0 - .unwrap(); + for aux in [None, some_aux.clone()] { + let key_id = SchnorrPublicKeyArgsKeyId { + algorithm: algorithm.clone(), + name: name.to_string(), + }; - // We verify the Schnorr signature. - match key_id.algorithm { - SchnorrAlgorithm::Bip340Secp256K1 => { - use k256::ecdsa::signature::hazmat::PrehashVerifier; - use k256::schnorr::{Signature, VerifyingKey}; - let vk = VerifyingKey::from_bytes(&schnorr_public_key.public_key[1..]).unwrap(); - let sig = Signature::try_from(schnorr_signature.as_slice()).unwrap(); - vk.verify_prehash(message, &sig).unwrap(); - } - SchnorrAlgorithm::Ed25519 => { - use ed25519_dalek::{Signature, Verifier, VerifyingKey}; - let pk: [u8; 32] = schnorr_public_key.public_key.try_into().unwrap(); - let vk = VerifyingKey::from_bytes(&pk).unwrap(); - let signature = Signature::from_slice(&schnorr_signature).unwrap(); - vk.verify(message, &signature).unwrap(); - } - }; + // We get the Schnorr public key and signature via update calls to the test canister. + let schnorr_public_key = update_candid::< + (Option, _, _), + (Result,), + >( + &pic, + canister, + "schnorr_public_key", + (None, derivation_path.clone(), key_id.clone()), + ) + .unwrap() + .0 + .unwrap(); + let schnorr_signature_result = update_candid::<_, (Result, String>,)>( + &pic, + canister, + "sign_with_schnorr", + ( + message, + derivation_path.clone(), + key_id.clone(), + aux.clone(), + ), + ) + .unwrap() + .0; + + // We verify the Schnorr signature. + match key_id.algorithm { + SchnorrAlgorithm::Bip340Secp256K1 => { + use k256::ecdsa::signature::hazmat::PrehashVerifier; + use k256::schnorr::{Signature, VerifyingKey}; + let bip340_public_key = schnorr_public_key.public_key[1..].to_vec(); + let public_key = match aux { + None => bip340_public_key, + Some(SignWithSchnorrAux::Bip341(bip341_aux)) => { + use bitcoin::hashes::Hash; + use bitcoin::schnorr::TapTweak; + let xonly = bitcoin::util::key::XOnlyPublicKey::from_slice( + bip340_public_key.as_slice(), + ) + .unwrap(); + let merkle_root = + bitcoin::util::taproot::TapBranchHash::from_slice( + &bip341_aux.merkle_root_hash, + ) + .unwrap(); + let secp256k1_engine = bitcoin::secp256k1::Secp256k1::new(); + xonly + .tap_tweak(&secp256k1_engine, Some(merkle_root)) + .0 + .to_inner() + .serialize() + .to_vec() + } + }; + let vk = VerifyingKey::from_bytes(&public_key).unwrap(); + let sig = Signature::try_from(schnorr_signature_result.unwrap().as_slice()) + .unwrap(); + + vk.verify_prehash(message, &sig).unwrap(); + } + SchnorrAlgorithm::Ed25519 => { + use ed25519_dalek::{Signature, Verifier, VerifyingKey}; + let pk: [u8; 32] = schnorr_public_key.public_key.try_into().unwrap(); + let vk = VerifyingKey::from_bytes(&pk).unwrap(); + let verification_result = schnorr_signature_result.map(|signature| { + let s = Signature::from_slice(&signature).unwrap(); + vk.verify(message, &s).unwrap(); + }); + assert!( + verification_result.is_ok() == aux.is_none(), + "{:?}", + verification_result + ); + } + }; + } } } } @@ -2128,3 +2171,35 @@ fn await_call_no_ticks() { }; assert_eq!(principal, canister_id.to_string()); } + +#[test] +fn many_intersubnet_calls() { + let pic = PocketIcBuilder::new() + .with_application_subnet() + .with_application_subnet() + .build(); + let canister_1 = pic.create_canister_on_subnet(None, None, pic.topology().get_app_subnets()[0]); + pic.add_cycles(canister_1, 100_000_000_000_000_000); + pic.install_canister(canister_1, test_canister_wasm(), vec![], None); + let canister_2 = pic.create_canister_on_subnet(None, None, pic.topology().get_app_subnets()[1]); + pic.add_cycles(canister_2, 100_000_000_000_000_000); + pic.install_canister(canister_2, test_canister_wasm(), vec![], None); + + let mut msg_ids = vec![]; + let num_msgs: usize = 500; + let msg_size: usize = 10000; + for _ in 0..num_msgs { + let msg_id = pic + .submit_call( + canister_1, + Principal::anonymous(), + "call_with_large_blob", + Encode!(&canister_2, &msg_size).unwrap(), + ) + .unwrap(); + msg_ids.push(msg_id); + } + for msg_id in msg_ids { + pic.await_call(msg_id).unwrap(); + } +} diff --git a/rs/boundary_node/ic_boundary/src/metrics.rs b/rs/boundary_node/ic_boundary/src/metrics.rs index d4d363f9788..6b8c1701295 100644 --- a/rs/boundary_node/ic_boundary/src/metrics.rs +++ b/rs/boundary_node/ic_boundary/src/metrics.rs @@ -500,8 +500,17 @@ pub async fn metrics_middleware( let ip_family = request .extensions() .get::>() - .map(|x| x.remote_addr.family()) - .unwrap_or("0"); + .map(|x| { + let f = x.remote_addr.family(); + if f == "v4" { + 4 + } else if f == "v6" { + 6 + } else { + 0 + } + }) + .unwrap_or(0); let remote_addr = request .extensions() diff --git a/rs/config/src/subnet_config.rs b/rs/config/src/subnet_config.rs index 3724a39fa5d..0bbefe812c5 100644 --- a/rs/config/src/subnet_config.rs +++ b/rs/config/src/subnet_config.rs @@ -140,7 +140,6 @@ const DEFAULT_REFERENCE_SUBNET_SIZE: usize = 13; /// Costs for each newly created dirty page in stable memory. const DEFAULT_DIRTY_PAGE_OVERHEAD: NumInstructions = NumInstructions::new(1_000); -const SYSTEM_SUBNET_DIRTY_PAGE_OVERHEAD: NumInstructions = NumInstructions::new(0); /// Accumulated priority reset interval, rounds. /// @@ -341,7 +340,7 @@ impl SchedulerConfig { // This limit should be high enough (1000T) to effectively disable // rate-limiting for the system subnets. install_code_rate_limit: NumInstructions::from(1_000_000_000_000_000), - dirty_page_overhead: SYSTEM_SUBNET_DIRTY_PAGE_OVERHEAD, + dirty_page_overhead: DEFAULT_DIRTY_PAGE_OVERHEAD, accumulated_priority_reset_interval: ACCUMULATED_PRIORITY_RESET_INTERVAL, upload_wasm_chunk_instructions: NumInstructions::from(0), canister_snapshot_baseline_instructions: NumInstructions::from(0), diff --git a/rs/consensus/benches/validate_payload.rs b/rs/consensus/benches/validate_payload.rs index 00d463268f0..db2b14d1507 100644 --- a/rs/consensus/benches/validate_payload.rs +++ b/rs/consensus/benches/validate_payload.rs @@ -10,7 +10,7 @@ //! in the past payloads, and the user signature is checked eventually, and //! the message validates successfully -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; use dkg::DkgDataPayload; use ic_artifact_pool::{consensus_pool::ConsensusPoolImpl, ingress_pool::IngressPoolImpl}; use ic_config::state_manager::Config as StateManagerConfig; @@ -80,7 +80,7 @@ const PAST_PAYLOAD_HEIGHT: u64 = 4; /// Ingress history size: 5 min worth of messages at 1000/sec = 300K. const INGRESS_HISTORY_SIZE: usize = 300_000; -fn run_test(_test_name: &str, test_fn: T) +fn run_test(test_fn: T) where T: FnOnce(Time, &mut ConsensusPoolImpl, &dyn PayloadBuilder), { @@ -233,13 +233,18 @@ fn setup_ingress_state(now: Time, state_manager: &mut StateManagerImpl) { /// Prepares the ingress payload which has 1K x specified number of /// SignedIngress messages. The payload is filled with the specified 'seed' /// bytes -fn prepare_ingress_payload(now: Time, message_count: usize, seed: u8) -> IngressPayload { +fn prepare_ingress_payload( + now: Time, + message_count: usize, + message_size: usize, + seed: u8, +) -> IngressPayload { let mut ingress_msgs = Vec::new(); let expiry = std::time::Duration::from_secs(MAX_INGRESS_TTL.as_secs() - 1); for i in 0..message_count { let ingress = SignedIngressBuilder::new() .method_name("provisional_create_canister_with_cycles") - .method_payload(vec![seed; INGRESS_MESSAGE_SIZE]) + .method_payload(vec![seed; message_size]) .nonce(i as u64) .expiry_time(now + expiry) .canister_id(IC_00) @@ -269,7 +274,7 @@ fn add_past_blocks( for i in 1..=to_add { let mut block = Block::from_parent(&parent); block.rank = Rank(i); - let ingress = prepare_ingress_payload(now, message_count, i as u8); + let ingress = prepare_ingress_payload(now, message_count, INGRESS_MESSAGE_SIZE, i as u8); block.payload = Payload::new( ic_types::crypto::crypto_hash, BlockPayload::Data(DataPayload { @@ -336,7 +341,6 @@ fn validate_payload_benchmark(criterion: &mut Criterion) { for message_count in (50..=850).step_by(50) { run_test( - "validate_payload_benchmark", |now: Time, consensus_pool: &mut ConsensusPoolImpl, payload_builder: &dyn PayloadBuilder| { @@ -344,7 +348,8 @@ fn validate_payload_benchmark(criterion: &mut Criterion) { let pool_reader = PoolReader::new(consensus_pool); let seed = CERTIFIED_HEIGHT + PAST_PAYLOAD_HEIGHT + 10; - let ingress = prepare_ingress_payload(now, message_count, seed as u8); + let ingress = + prepare_ingress_payload(now, message_count, INGRESS_MESSAGE_SIZE, seed as u8); let payload = Payload::new( ic_types::crypto::crypto_hash, BlockPayload::Data(DataPayload { @@ -359,8 +364,7 @@ fn validate_payload_benchmark(criterion: &mut Criterion) { }), ); - let name = format!("validate_payload_{}", message_count); - group.bench_function(&name, |bench| { + group.bench_function(format!("validate_payload_{}", message_count), |bench| { bench.iter(|| { validate_payload(now, &payload, &pool_reader, &tip, payload_builder) .expect("Invalid payload") @@ -372,31 +376,39 @@ fn validate_payload_benchmark(criterion: &mut Criterion) { } fn serialization_benchmark(criterion: &mut Criterion) { - let mut group = criterion.benchmark_group("serialization"); - group.sample_size(30); + let mut group = criterion.benchmark_group("ingress_payload_serialization_deserialization"); + group.sample_size(50); group.measurement_time(std::time::Duration::from_secs(10)); - for message_count in (2000..=8000).step_by(2000) { + for (message_count, message_size_kb, tag) in [ + (1_000, 4_000, "1000x4KB"), + (2_000, 4_000, "2000x4KB"), + (1, 4_000_000, "1x4MB"), + (1, 8_000_000, "1x8MB"), + ] { run_test( - "serialization_benchmark", |now: Time, _: &mut ConsensusPoolImpl, _: &dyn PayloadBuilder| { let seed = CERTIFIED_HEIGHT + PAST_PAYLOAD_HEIGHT + 10; - let ingress = prepare_ingress_payload(now, message_count, seed as u8); - let name = format!("serialization_{}_kb_payload", message_count); - group.bench_function(&name, |bench| { + let ingress = + prepare_ingress_payload(now, message_count, message_size_kb, seed as u8); + + group.bench_function(format!("serialization_{tag}"), |bench| { bench.iter(|| { let proto: pb::IngressPayload = (&ingress).into(); black_box(proto); }) }); - let name = format!("deserialization_{}_kb_payload", message_count); - group.bench_function(&name, |bench| { + + group.bench_function(format!("deserialization_{tag}"), |bench| { let p: pb::IngressPayload = (&ingress).into(); - bench.iter(|| { - let proto = p.clone(); - let deser: IngressPayload = proto.try_into().unwrap(); - black_box(deser); - }) + bench.iter_batched( + || p.clone(), + |proto| { + let deser: IngressPayload = proto.try_into().unwrap(); + black_box(deser); + }, + BatchSize::LargeInput, + ) }); }, ) diff --git a/rs/crypto/internal/crypto_service_provider/src/vault/local_csp_vault/vetkd/tests.rs b/rs/crypto/internal/crypto_service_provider/src/vault/local_csp_vault/vetkd/tests.rs index ae543665a57..6a5e13a5c32 100644 --- a/rs/crypto/internal/crypto_service_provider/src/vault/local_csp_vault/vetkd/tests.rs +++ b/rs/crypto/internal/crypto_service_provider/src/vault/local_csp_vault/vetkd/tests.rs @@ -15,7 +15,7 @@ use rand_chacha::ChaCha20Rng; #[test] fn should_correctly_create_encrypted_vetkd_key_share() { - let rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let result = create_encrypted_vetkd_key_share(rng); @@ -24,7 +24,7 @@ fn should_correctly_create_encrypted_vetkd_key_share() { #[test] fn should_correctly_create_encrypted_vetkd_key_share_for_smoke_test_vector() { - let rng = ChaCha20Rng::seed_from_u64(123); + let rng = &mut ChaCha20Rng::seed_from_u64(123); let result = create_encrypted_vetkd_key_share(rng); @@ -32,80 +32,36 @@ fn should_correctly_create_encrypted_vetkd_key_share_for_smoke_test_vector() { result, Ok(VetKdEncryptedKeyShareContent( hex::decode( - "8fb20ba0025e22ebc546852eca21e324cfc96c8b7b127b9c6790d5f5a2d1a7\ - 2ad7c18c852215b44e3fe0315203b9565fafc0c7d8178ba92f0d6dca8c79d48\ - 8c9f9ebf1469af0ebad6908c0edbd4c546a21ba9e1530732de2748f1c54ddbb\ - 2a6406a9ad976f0487ec4d0063aec5f27301eeaeb47d3977d9a472dacdc8ad7\ - 546c1f26453229d6f1aa612ea109e1ad4a05d9352b91693c734f7207002e2f9\ - da6ac9dac0aefe136247b46d44c763d33718604c6340e8c9c9fe388af7e3c93\ - 3fc9255", + "a8d7c58088640a9639267c5843824ee31f6ed8c6a90ea31e05a12459ea2498\ + f3e68e13f62604d027660883213c90ea72810bcecee58b883fb62118e538243\ + 03718e6876ea400d083beb0439d3934122a4c4b2e58e3f145305b9a0c0a00e3\ + 2dd808574dec2605dbc7f122fe593ca0c07ca92720d0f17b7d53c9c68dbb93d\ + 489078859e5e5fe2b6612ac9536fe7f8b463cac948e6db97908b7f5a67b33b3\ + e60a1c160889ef49448519a84be1aba0611829a7cca180cbbdf94f7b2cda2db\ + 6b14c65", ) .expect("invalid test vector") )) ); } -fn create_encrypted_vetkd_key_share( - mut rng: R, +fn create_encrypted_vetkd_key_share( + rng: &mut R, ) -> Result { - let master_secret_key = Scalar::random(&mut rng); - let master_public_key = G2Affine::from(G2Affine::generator() * &master_secret_key); - let encryption_public_key = TransportSecretKey::generate(&mut rng).public_key(); - let key_id = KeyId::from([123; 32]); - - let mut node_sks = MockSecretKeyStore::new(); - node_sks - .expect_get() - .times(1) - .withf(move |key_id_| *key_id_ == key_id) - .return_const(Some(CspSecretKey::ThresBls12_381( - threshold_types::SecretKeyBytes::from(&master_secret_key), - ))); - - let derivation_path = ExtendedDerivationPath { - caller: canister_test_id(234).get(), - derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], - }; - let derivation_id = b"some-derivation-id".to_vec(); - - let vault = LocalCspVault::builder_for_test() - .with_rng(rng) - .with_mock_stores() - .with_node_secret_key_store(node_sks) - .build(); - - vault.create_encrypted_vetkd_key_share( - key_id, - master_public_key.serialize().to_vec(), - encryption_public_key.serialize().to_vec(), - derivation_path, - derivation_id, - ) + let test_env = CreateVetKdKeyShareTestSetup::new(rng); + + test_env.create_encrypted_vetkd_key_share() } #[test] fn should_fail_to_create_key_share_with_invalid_master_public_key() { let rng = &mut reproducible_rng(); - let invalid_master_public_key = b"invalid-master-public-key".to_vec(); - let encryption_public_key = TransportSecretKey::generate(rng).public_key(); - let key_id = KeyId::from([123; 32]); - - let derivation_path = ExtendedDerivationPath { - caller: canister_test_id(234).get(), - derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], - }; - let derivation_id = b"some-derivation-id".to_vec(); + let mut test_env = CreateVetKdKeyShareTestSetup::new(rng); + test_env.master_public_key = b"invalid-master-public-key".to_vec(); + test_env.secret_key_store_override = Some(MockSecretKeyStore::new()); - let vault = LocalCspVault::builder_for_test().with_mock_stores().build(); - - let result = vault.create_encrypted_vetkd_key_share( - key_id, - invalid_master_public_key, - encryption_public_key.serialize().to_vec(), - derivation_path, - derivation_id, - ); + let result = test_env.create_encrypted_vetkd_key_share(); assert_matches!( result, Err(VetKdEncryptedKeyShareCreationVaultError::InvalidArgument(error)) @@ -115,31 +71,13 @@ fn should_fail_to_create_key_share_with_invalid_master_public_key() { #[test] fn should_fail_to_create_key_share_with_invalid_encryption_public_key() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); - let master_secret_key = Scalar::random(&mut rng); - let master_public_key = G2Affine::from(G2Affine::generator() * &master_secret_key); - let invalid_encryption_public_key = b"invalid-encryption-public-key".to_vec(); - let key_id = KeyId::from([123; 32]); - - let derivation_path = ExtendedDerivationPath { - caller: canister_test_id(234).get(), - derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], - }; - let derivation_id = b"some-derivation-id".to_vec(); - - let vault = LocalCspVault::builder_for_test() - .with_rng(rng) - .with_mock_stores() - .build(); - - let result = vault.create_encrypted_vetkd_key_share( - key_id, - master_public_key.serialize().to_vec(), - invalid_encryption_public_key, - derivation_path, - derivation_id, - ); + let mut test_env = CreateVetKdKeyShareTestSetup::new(rng); + test_env.transport_public_key = b"invalid-encryption-public-key".to_vec(); + test_env.secret_key_store_override = Some(MockSecretKeyStore::new()); + + let result = test_env.create_encrypted_vetkd_key_share(); assert_matches!( result, Err(VetKdEncryptedKeyShareCreationVaultError::InvalidArgument(error)) @@ -150,38 +88,11 @@ fn should_fail_to_create_key_share_with_invalid_encryption_public_key() { #[test] fn should_fail_to_create_key_share_if_key_is_missing_in_secret_key_store() { let mut rng = reproducible_rng(); + let mut test_env = CreateVetKdKeyShareTestSetup::new(&mut rng); - let master_secret_key = Scalar::random(&mut rng); - let master_public_key = G2Affine::from(G2Affine::generator() * &master_secret_key); - let encryption_public_key = TransportSecretKey::generate(&mut rng).public_key(); - let key_id = KeyId::from([123; 32]); - - let mut node_sks = MockSecretKeyStore::new(); - node_sks - .expect_get() - .times(1) - .withf(move |key_id_| *key_id_ == key_id) - .return_const(None); - - let derivation_path = ExtendedDerivationPath { - caller: canister_test_id(234).get(), - derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], - }; - let derivation_id = b"some-derivation-id".to_vec(); - - let vault = LocalCspVault::builder_for_test() - .with_rng(rng) - .with_mock_stores() - .with_node_secret_key_store(node_sks) - .build(); - - let result = vault.create_encrypted_vetkd_key_share( - key_id, - master_public_key.serialize().to_vec(), - encryption_public_key.serialize().to_vec(), - derivation_path, - derivation_id, - ); + test_env.secret_key_store_return_override = Some(None); + + let result = test_env.create_encrypted_vetkd_key_share(); assert_matches!( result, Err(VetKdEncryptedKeyShareCreationVaultError::InvalidArgument(error)) @@ -192,43 +103,95 @@ fn should_fail_to_create_key_share_if_key_is_missing_in_secret_key_store() { #[test] fn should_fail_to_create_key_share_if_key_in_secret_key_store_has_wrong_type() { let mut rng = reproducible_rng(); + let mut test_env = CreateVetKdKeyShareTestSetup::new(&mut rng); - let master_secret_key = Scalar::random(&mut rng); - let master_public_key = G2Affine::from(G2Affine::generator() * &master_secret_key); - let encryption_public_key = TransportSecretKey::generate(&mut rng).public_key(); - let key_id = KeyId::from([123; 32]); - - let mut node_sks = MockSecretKeyStore::new(); - node_sks - .expect_get() - .times(1) - .withf(move |key_id_| *key_id_ == key_id) - .return_const(Some(CspSecretKey::MultiBls12_381( - multi_types::SecretKeyBytes::from(&master_secret_key), - ))); - - let derivation_path = ExtendedDerivationPath { - caller: canister_test_id(234).get(), - derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], - }; - let derivation_id = b"some-derivation-id".to_vec(); - - let vault = LocalCspVault::builder_for_test() - .with_rng(rng) - .with_mock_stores() - .with_node_secret_key_store(node_sks) - .build(); - - let result = vault.create_encrypted_vetkd_key_share( - key_id, - master_public_key.serialize().to_vec(), - encryption_public_key.serialize().to_vec(), - derivation_path, - derivation_id, - ); + test_env.secret_key_store_return_override = Some(Some(CspSecretKey::MultiBls12_381( + multi_types::SecretKeyBytes::from(&test_env.master_secret_key), + ))); + + let result = test_env.create_encrypted_vetkd_key_share(); assert_matches!( result, Err(VetKdEncryptedKeyShareCreationVaultError::InvalidArgument(error)) if error.contains("wrong secret key type") ); } + +struct CreateVetKdKeyShareTestSetup { + key_id: KeyId, + master_public_key: Vec, + transport_public_key: Vec, + derivation_path: ExtendedDerivationPath, + derivation_id: Vec, + master_secret_key: Scalar, + rng: ChaCha20Rng, + secret_key_store_override: Option, + secret_key_store_return_override: Option>, +} + +impl CreateVetKdKeyShareTestSetup { + pub fn new(rng: &mut R) -> Self { + let master_secret_key = Scalar::random(rng); + let master_public_key = G2Affine::from(G2Affine::generator() * &master_secret_key); + let transport_secret_key = TransportSecretKey::generate(rng); + let key_id = KeyId::from([123; 32]); + let derivation_path = ExtendedDerivationPath { + caller: canister_test_id(234).get(), + derivation_path: vec![b"some".to_vec(), b"derivation".to_vec(), b"path".to_vec()], + }; + let derivation_id = b"some-derivation-id".to_vec(); + let rng = ChaCha20Rng::from_seed(rng.gen()); + + Self { + master_secret_key, + master_public_key: master_public_key.serialize().to_vec(), + transport_public_key: transport_secret_key.public_key().serialize().to_vec(), + key_id, + derivation_path, + derivation_id, + rng, + secret_key_store_override: None, + secret_key_store_return_override: None, + } + } + + pub fn create_encrypted_vetkd_key_share( + self, + ) -> Result { + let node_sks = if let Some(node_sks_override) = self.secret_key_store_override { + node_sks_override + } else { + let return_value = if let Some(opt_sk) = self.secret_key_store_return_override { + opt_sk + } else { + Some(CspSecretKey::ThresBls12_381( + threshold_types::SecretKeyBytes::from(&self.master_secret_key), + )) + }; + let mut node_sks = MockSecretKeyStore::new(); + node_sks + .expect_get() + .times(1) + .withf({ + let self_key_id = self.key_id; + move |key_id_| key_id_ == &self_key_id + }) + .return_const(return_value); + node_sks + }; + + let vault = LocalCspVault::builder_for_test() + .with_rng(self.rng) + .with_mock_stores() + .with_node_secret_key_store(node_sks) + .build(); + + vault.create_encrypted_vetkd_key_share( + self.key_id, + self.master_public_key.clone(), + self.transport_public_key.clone(), + self.derivation_path.clone(), + self.derivation_id.clone(), + ) + } +} diff --git a/rs/embedders/fuzz/BUILD.bazel b/rs/embedders/fuzz/BUILD.bazel index 0dc8718a006..493b36377ef 100644 --- a/rs/embedders/fuzz/BUILD.bazel +++ b/rs/embedders/fuzz/BUILD.bazel @@ -41,6 +41,7 @@ rust_library( "//rs/types/types", "//rs/types/wasm_types", "@crate_index//:arbitrary", + "@crate_index//:futures", "@crate_index//:lazy_static", "@crate_index//:libfuzzer-sys", "@crate_index//:tokio", @@ -121,7 +122,7 @@ rust_fuzz_test_binary_afl( deps = [":wasm_fuzzers"] + ["@crate_index//:libfuzzer-sys"], ) -rust_fuzz_test_binary( +rust_fuzz_test_binary_afl( name = "compile_wasm_using_embedder", srcs = ["fuzz_targets/compile_wasm_using_embedder.rs"], proc_macro_deps = MACRO_DEPENDENCIES, diff --git a/rs/embedders/fuzz/fuzz_targets/compile_wasm_using_embedder.rs b/rs/embedders/fuzz/fuzz_targets/compile_wasm_using_embedder.rs index 921bbcb232a..8f3dc85f78c 100644 --- a/rs/embedders/fuzz/fuzz_targets/compile_wasm_using_embedder.rs +++ b/rs/embedders/fuzz/fuzz_targets/compile_wasm_using_embedder.rs @@ -1,8 +1,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; use wasm_fuzzers::compile::run_fuzzer; -use wasm_fuzzers::compile::MaybeInvalidModule; -fuzz_target!(|module: MaybeInvalidModule| { +fuzz_target!(|module: &[u8]| { run_fuzzer(module); }); diff --git a/rs/embedders/fuzz/src/compile.rs b/rs/embedders/fuzz/src/compile.rs index 1af30a58758..e552de23070 100644 --- a/rs/embedders/fuzz/src/compile.rs +++ b/rs/embedders/fuzz/src/compile.rs @@ -1,44 +1,134 @@ +use crate::ic_wasm::{generate_exports, ic_embedders_config, ic_wasm_config}; use arbitrary::{Arbitrary, Result, Unstructured}; -use ic_config::embedders::Config as EmbeddersConfig; -use ic_config::flag_status::FlagStatus; use ic_embedders::{wasm_utils::compile, WasmtimeEmbedder}; use ic_logger::replica_logger::no_op_logger; use ic_wasm_types::BinaryEncodedWasm; -use wasm_smith::{Config, Module}; +use std::time::Duration; +use tokio::runtime::Runtime; +use wasm_smith::{Config, MemoryOffsetChoices, Module}; #[derive(Debug)] -pub struct MaybeInvalidModule(pub Module); +pub struct MaybeInvalidModule { + pub module: Module, + pub memory64_enabled: bool, +} + +const MAX_PARALLEL_EXECUTIONS: usize = 4; impl<'a> Arbitrary<'a> for MaybeInvalidModule { fn arbitrary(u: &mut Unstructured<'a>) -> Result { - let mut config = Config::arbitrary(u)?; + let mut config = if u.ratio(1, 2)? { + let memory64_enabled = u.ratio(2, 3)?; + let mut config = ic_wasm_config(ic_embedders_config(memory64_enabled)); + config.exports = generate_exports(ic_embedders_config(memory64_enabled), u)?; + config.min_data_segments = 2; + config.max_data_segments = 10; + config + } else { + Config::arbitrary(u)? + }; config.allow_invalid_funcs = true; - Ok(MaybeInvalidModule(Module::new(config, u)?)) + config.memory_offset_choices = MemoryOffsetChoices(40, 20, 40); + Ok(MaybeInvalidModule { + module: Module::new(config.clone(), u)?, + memory64_enabled: config.memory64_enabled, + }) } } #[inline(always)] -pub fn run_fuzzer(module: MaybeInvalidModule) { - let mut config = EmbeddersConfig::default(); - config.feature_flags.wasm64 = FlagStatus::Enabled; - let wasm = module.0.to_bytes(); - let binary_wasm = BinaryEncodedWasm::new(wasm); - let embedder = WasmtimeEmbedder::new(config, no_op_logger()); - - let (_, _) = compile(&embedder, &binary_wasm); +pub fn run_fuzzer(bytes: &[u8]) { + let config; + let mut u = Unstructured::new(bytes); + + // Arbitrary Wasm module generation probabilities + // 33% - Random bytes + // 33% - Wasm with arbitrary wasm-smith config + maybe invalid functions + // 33% - IC compliant wasm + maybe invalid functions + + // Only used w/ random bytes + let memory64_enabled = u.ratio(1, 2).unwrap_or(false); + + let wasm = if u.ratio(1, 3).unwrap_or(false) + || bytes.len() < ::size_hint(0).0 + { + config = ic_embedders_config(memory64_enabled); + raw_wasm_bytes(bytes) + } else { + let data = ::arbitrary_take_rest(u); + + match data { + Ok(data) => { + config = ic_embedders_config(data.memory64_enabled); + data.module.to_bytes() + } + Err(_) => { + config = ic_embedders_config(memory64_enabled); + raw_wasm_bytes(bytes) + } + } + }; + + let rt: Runtime = tokio::runtime::Builder::new_multi_thread() + .worker_threads(6) + .max_blocking_threads(2) + .enable_all() + .build() + .unwrap_or_else(|err| panic!("Could not create tokio runtime: {}", err)); + + let futs = (0..MAX_PARALLEL_EXECUTIONS) + .map(|_| { + rt.spawn({ + let wasm = wasm.clone(); + let binary_wasm = BinaryEncodedWasm::new(wasm); + let embedder = WasmtimeEmbedder::new(config.clone(), no_op_logger()); + + async move { compile(&embedder, &binary_wasm) } + }) + }) + .collect::>(); + + rt.block_on(async move { + // The omitted field is EmbedderCache(Result, HypervisorError>) + // 1. InstancePre doesn't implement PartialEq + // 2. HypervisorError is the same in compilation_result which is checked for equality + + let result = futures::future::join_all(futs) + .await + .into_iter() + .map(|r| r.expect("Failed to join tasks")) + .map(|(_, compilation_result)| { + if let Ok(mut r) = compilation_result { + r.0.compilation_time = Duration::from_millis(1); + Ok(r) + } else { + compilation_result + } + }) + .collect::>(); + + let first = result.first(); + + if let Some(first) = first { + assert!(result.iter().all(|r| r == first)); + } + }); +} + +#[inline(always)] +fn raw_wasm_bytes(data: &[u8]) -> Vec { + let mut wasm: Vec = b"\x00asm".to_vec(); + wasm.extend_from_slice(data); + wasm } #[cfg(test)] mod tests { use super::*; - use arbitrary::{Arbitrary, Unstructured}; #[test] fn test_compile_wasm_using_embedder_single_run() { let arbitrary_str: &str = "this is a test string"; - let unstrucutred = Unstructured::new(arbitrary_str.as_bytes()); - let module = ::arbitrary_take_rest(unstrucutred) - .expect("Unable to extract wasm from Unstructured data"); - run_fuzzer(module); + run_fuzzer(arbitrary_str.as_bytes()); } } diff --git a/rs/embedders/fuzz/src/differential.rs b/rs/embedders/fuzz/src/differential.rs index deb60a00d3c..5c0192f46a6 100644 --- a/rs/embedders/fuzz/src/differential.rs +++ b/rs/embedders/fuzz/src/differential.rs @@ -1,6 +1,4 @@ -use crate::ic_wasm::ICWasmModule; -use ic_config::embedders::Config as EmbeddersConfig; -use ic_config::flag_status::FlagStatus; +use crate::ic_wasm::{ic_embedders_config, ICWasmModule}; use ic_embedders::InstanceRunResult; use ic_interfaces::execution_environment::HypervisorResult; use ic_interfaces::execution_environment::SystemApi; @@ -11,10 +9,18 @@ use ic_types::methods::{FuncRef, WasmMethod}; use std::collections::BTreeSet; use tokio::runtime::Runtime; +const MAX_PARALLEL_EXECUTIONS: usize = 2; +type DeterministicExecutionResult = Vec<( + HypervisorResult>, + HypervisorResult, + u64, +)>; + #[inline(always)] pub fn run_fuzzer(module: ICWasmModule) { let wasm = module.module.to_bytes(); let wasm_methods: BTreeSet = module.exported_functions; + let memory64_enabled = module.config.memory64_enabled; if wasm_methods.is_empty() { return; @@ -29,88 +35,99 @@ pub fn run_fuzzer(module: ICWasmModule) { .build() .unwrap_or_else(|err| panic!("Could not create tokio runtime: {}", err)); - let first_execution = rt.spawn({ - let wasm = wasm.clone(); - let wasm_methods = wasm_methods.clone(); - - async move { execute_wasm(wasm, wasm_methods) } - }); + let futs = (0..MAX_PARALLEL_EXECUTIONS) + .map(|_| { + rt.spawn({ + let wasm = wasm.clone(); + let wasm_methods = wasm_methods.clone(); - let second_execution = rt.spawn(async move { execute_wasm(wasm, wasm_methods) }); + async move { execute_wasm(wasm, wasm_methods, memory64_enabled) } + }) + }) + .collect::>(); rt.block_on(async move { - let first = first_execution.await.unwrap(); - let second = second_execution.await.unwrap(); - - // same size - assert_eq!(first.len(), second.len()); - - for (x, y) in std::iter::zip(first, second) { - // execution result must be same - assert_eq!(x.0, y.0); - - // instructions used must be same - assert_eq!(x.2, y.2); - - match (x.1, y.1) { - (Ok(run_x), Ok(run_y)) => { - assert_eq!(run_x.wasm_dirty_pages, run_y.wasm_dirty_pages); - assert_eq!( - run_x.stable_memory_dirty_pages, - run_y.stable_memory_dirty_pages - ); - - // special treatment because of NaN - let globals_x = run_x.exported_globals; - let globals_y = run_y.exported_globals; - for (g_x, g_y) in std::iter::zip(globals_x, globals_y) { - match (g_x, g_y) { - (Global::F32(f_x), Global::F32(f_y)) => { - if !f_x.is_nan() && !f_y.is_nan() { - assert_eq!(f_x, f_y); - } else { - // should hold because of canonicalization - assert_eq!(f_x.to_bits(), f_y.to_bits()); - } - } - (Global::F64(f_x), Global::F64(f_y)) => { - if !f_x.is_nan() && !f_y.is_nan() { - assert_eq!(f_x, f_y); - } else { - // should hold because of canonicalization - assert_eq!(f_x.to_bits(), f_y.to_bits()); - } + let result = futures::future::join_all(futs) + .await + .into_iter() + .map(|r| r.expect("Failed to join tasks")) + .collect::>(); + + let first = result.first(); + + if let Some(first) = first { + result + .iter() + .for_each(|r| equal(first.to_vec(), r.to_vec())); + } + }); +} + +// Panics if the results are not equal +fn equal(first: DeterministicExecutionResult, second: DeterministicExecutionResult) { + // same size + assert_eq!(first.len(), second.len()); + + for (x, y) in std::iter::zip(first, second) { + // execution result must be same + assert_eq!(x.0, y.0); + + // instructions used must be same + assert_eq!(x.2, y.2); + + match (x.1, y.1) { + (Ok(run_x), Ok(run_y)) => { + assert_eq!(run_x.wasm_dirty_pages, run_y.wasm_dirty_pages); + assert_eq!( + run_x.stable_memory_dirty_pages, + run_y.stable_memory_dirty_pages + ); + + // special treatment because of NaN + let globals_x = run_x.exported_globals; + let globals_y = run_y.exported_globals; + for (g_x, g_y) in std::iter::zip(globals_x, globals_y) { + match (g_x, g_y) { + (Global::F32(f_x), Global::F32(f_y)) => { + if !f_x.is_nan() && !f_y.is_nan() { + assert_eq!(f_x, f_y); + } else { + // should hold because of canonicalization + assert_eq!(f_x.to_bits(), f_y.to_bits()); } - (_, _) => { - assert_eq!(g_x, g_y); + } + (Global::F64(f_x), Global::F64(f_y)) => { + if !f_x.is_nan() && !f_y.is_nan() { + assert_eq!(f_x, f_y); + } else { + // should hold because of canonicalization + assert_eq!(f_x.to_bits(), f_y.to_bits()); } } + (_, _) => { + assert_eq!(g_x, g_y); + } } } - (Err(e_x), Err(e_y)) => { - assert_eq!(e_x, e_y); - } - (_, _) => { - panic!("Instance results doesn't match"); - } + } + (Err(e_x), Err(e_y)) => { + assert_eq!(e_x, e_y); + } + (_, _) => { + panic!("Instance results doesn't match"); } } - }); + } } #[inline(always)] fn execute_wasm( wasm: Vec, wasm_methods: BTreeSet, -) -> Vec<( - HypervisorResult>, - HypervisorResult, - u64, -)> { + memory64_enabled: bool, +) -> DeterministicExecutionResult { let mut result = vec![]; - let mut config = EmbeddersConfig::default(); - config.feature_flags.write_barrier = FlagStatus::Enabled; - config.feature_flags.wasm64 = FlagStatus::Enabled; + let config = ic_embedders_config(memory64_enabled); let instance_result = WasmtimeInstanceBuilder::new() .with_wasm(wasm) .with_config(config) diff --git a/rs/embedders/fuzz/src/ic_wasm.rs b/rs/embedders/fuzz/src/ic_wasm.rs index 73f788290d9..05ef46a01c9 100644 --- a/rs/embedders/fuzz/src/ic_wasm.rs +++ b/rs/embedders/fuzz/src/ic_wasm.rs @@ -1,6 +1,7 @@ use crate::imports::system_api_imports; use arbitrary::{Arbitrary, Result, Unstructured}; use ic_config::embedders::Config as EmbeddersConfig; +use ic_config::flag_status::FlagStatus; use ic_embedders::wasm_utils::validation::{RESERVED_SYMBOLS, WASM_FUNCTION_SIZE_LIMIT}; use ic_replicated_state::Global; use ic_types::methods::WasmMethod; @@ -16,7 +17,8 @@ use wasm_smith::{Config, Module}; use wasmparser::*; lazy_static! { - static ref SYSTEM_API_IMPORTS: Vec = system_api_imports(); + static ref SYSTEM_API_IMPORTS_WASM32: Vec = system_api_imports(ic_embedders_config(false)); + static ref SYSTEM_API_IMPORTS_WASM64: Vec = system_api_imports(ic_embedders_config(true)); } #[derive(Debug)] @@ -34,7 +36,8 @@ pub struct ICWasmModule { impl<'a> Arbitrary<'a> for ICWasmModule { fn arbitrary(u: &mut Unstructured<'a>) -> Result { - let embedder_config = EmbeddersConfig::new(); + let memory64_enabled = u.ratio(2, 3)?; + let embedder_config = ic_embedders_config(memory64_enabled); let exports = generate_exports(embedder_config.clone(), u)?; let mut config = ic_wasm_config(embedder_config); config.exports = exports; @@ -130,7 +133,8 @@ impl ICWasmModule { } } -fn ic_wasm_config(embedder_config: EmbeddersConfig) -> Config { +pub fn ic_wasm_config(embedder_config: EmbeddersConfig) -> Config { + let memory64_enabled = embedder_config.feature_flags.wasm64 == FlagStatus::Enabled; Config { min_funcs: 10, min_exports: 10, @@ -148,18 +152,33 @@ fn ic_wasm_config(embedder_config: EmbeddersConfig) -> Config { bulk_memory_enabled: true, reference_types_enabled: true, simd_enabled: true, - memory64_enabled: true, + memory64_enabled, threads_enabled: false, relaxed_simd_enabled: false, canonicalize_nans: false, exceptions_enabled: false, - available_imports: Some(SYSTEM_API_IMPORTS.to_vec()), + available_imports: Some(if memory64_enabled { + SYSTEM_API_IMPORTS_WASM64.to_vec() + } else { + SYSTEM_API_IMPORTS_WASM32.to_vec() + }), ..Default::default() } } +pub fn ic_embedders_config(memory64_enabled: bool) -> EmbeddersConfig { + let mut config = EmbeddersConfig::default(); + config.feature_flags.write_barrier = FlagStatus::Enabled; + if memory64_enabled { + config.feature_flags.wasm64 = FlagStatus::Enabled; + } else { + config.feature_flags.wasm64 = FlagStatus::Disabled; + } + config +} + fn get_persisted_global(g: wasmparser::Global) -> Option { match g.ty.content_type { ValType::I32 => Some(Global::I32( @@ -200,7 +219,7 @@ fn get_persisted_global(g: wasmparser::Global) -> Option { } } -fn generate_exports( +pub fn generate_exports( embedder_config: EmbeddersConfig, u: &mut Unstructured, ) -> Result>> { diff --git a/rs/embedders/fuzz/src/imports.rs b/rs/embedders/fuzz/src/imports.rs index 8ab106e8b8c..e0b34a85bfe 100644 --- a/rs/embedders/fuzz/src/imports.rs +++ b/rs/embedders/fuzz/src/imports.rs @@ -20,12 +20,7 @@ use wasm_encoder::{ }; use wasmtime::{Engine, Extern, Store, StoreLimits, ValType}; -pub(crate) fn system_api_imports() -> Vec { - let system_api_type = WasmMemoryType::Wasm64; - let mut config = EmbeddersConfig::default(); - config.feature_flags.write_barrier = FlagStatus::Enabled; - config.feature_flags.wasm64 = FlagStatus::Enabled; - +pub(crate) fn system_api_imports(config: EmbeddersConfig) -> Vec { let engine = Engine::new(&WasmtimeEmbedder::wasmtime_execution_config(&config)) .expect("Failed to initialize Wasmtime engine"); let api_type = ApiType::init(UNIX_EPOCH, vec![], user_test_id(24).get()); @@ -60,13 +55,27 @@ pub(crate) fn system_api_imports() -> Vec { }, ); let mut linker: wasmtime::Linker = wasmtime::Linker::new(&engine); - system_api::syscalls::( - &mut linker, - config.feature_flags, - config.stable_memory_dirty_page_limit, - config.stable_memory_accessed_page_limit, - system_api_type, - ); + + match config.feature_flags.wasm64 { + FlagStatus::Enabled => { + system_api::syscalls::( + &mut linker, + config.feature_flags, + config.stable_memory_dirty_page_limit, + config.stable_memory_accessed_page_limit, + WasmMemoryType::Wasm64, + ); + } + FlagStatus::Disabled => { + system_api::syscalls::( + &mut linker, + config.feature_flags, + config.stable_memory_dirty_page_limit, + config.stable_memory_accessed_page_limit, + WasmMemoryType::Wasm32, + ); + } + } // to avoid store move let mut system_api_imports: Vec<(&str, &str, wasmtime::Func)> = linker diff --git a/rs/embedders/fuzz/src/wasm_executor.rs b/rs/embedders/fuzz/src/wasm_executor.rs index 7946e421c79..81c0e605eb0 100644 --- a/rs/embedders/fuzz/src/wasm_executor.rs +++ b/rs/embedders/fuzz/src/wasm_executor.rs @@ -1,8 +1,6 @@ -use crate::ic_wasm::ICWasmModule; +use crate::ic_wasm::{ic_embedders_config, ICWasmModule}; use ic_config::{ - embedders::{Config, FeatureFlags}, - execution_environment::Config as HypervisorConfig, - flag_status::FlagStatus, + execution_environment::Config as HypervisorConfig, flag_status::FlagStatus, subnet_config::SchedulerConfig, }; use ic_cycles_account_manager::ResourceSaturation; @@ -59,14 +57,7 @@ pub fn run_fuzzer(module: ICWasmModule) { let wasm_methods: BTreeSet = module.exported_functions; let log = no_op_logger(); - let embedder_config = Config { - feature_flags: FeatureFlags { - write_barrier: FlagStatus::Enabled, - wasm64: FlagStatus::Enabled, - ..Default::default() - }, - ..Default::default() - }; + let embedder_config = ic_embedders_config(module.config.memory64_enabled); let metrics_registry = MetricsRegistry::new(); let fd_factory = Arc::new(TestPageAllocatorFileDescriptorImpl::new()); diff --git a/rs/embedders/fuzz/src/wasmtime.rs b/rs/embedders/fuzz/src/wasmtime.rs index 739eec0d854..b2911eb33b1 100644 --- a/rs/embedders/fuzz/src/wasmtime.rs +++ b/rs/embedders/fuzz/src/wasmtime.rs @@ -1,6 +1,4 @@ -use crate::ic_wasm::ICWasmModule; -use ic_config::embedders::Config as EmbeddersConfig; -use ic_config::flag_status::FlagStatus; +use crate::ic_wasm::{ic_embedders_config, ICWasmModule}; use ic_test_utilities_embedders::WasmtimeInstanceBuilder; use ic_types::methods::{FuncRef, WasmMethod}; use libfuzzer_sys::Corpus; @@ -11,9 +9,7 @@ pub fn run_fuzzer(module: ICWasmModule) -> Corpus { let wasm = module.module.to_bytes(); let wasm_methods: BTreeSet = module.exported_functions; - let mut config = EmbeddersConfig::default(); - config.feature_flags.write_barrier = FlagStatus::Enabled; - config.feature_flags.wasm64 = FlagStatus::Enabled; + let config = ic_embedders_config(module.config.memory64_enabled); let instance_result = WasmtimeInstanceBuilder::new() .with_wasm(wasm) diff --git a/rs/embedders/fuzz/src/ws2wasm.rs b/rs/embedders/fuzz/src/ws2wasm.rs index 6a7dfd152a8..c9e9f8797f2 100644 --- a/rs/embedders/fuzz/src/ws2wasm.rs +++ b/rs/embedders/fuzz/src/ws2wasm.rs @@ -1,6 +1,5 @@ use arbitrary::{Arbitrary, Unstructured}; use clap::Parser; -use ic_config::embedders::Config as EmbeddersConfig; use ic_logger::replica_logger::no_op_logger; use std::fs::File; use std::io; @@ -8,7 +7,7 @@ use std::io::prelude::*; use std::io::BufReader; use std::path::PathBuf; use std::sync::Arc; -use wasm_fuzzers::ic_wasm::ICWasmModule; +use wasm_fuzzers::ic_wasm::{ic_embedders_config, ICWasmModule}; use wasmprinter::print_bytes; use ic_embedders::{ @@ -57,7 +56,7 @@ fn main() -> io::Result<()> { let instrumentation = CommandLineArgs::parse().inst; if instrumentation { - let config = EmbeddersConfig::default(); + let config = ic_embedders_config(module.config.memory64_enabled); let decoded = decode_wasm(config.wasm_max_size, Arc::new(wasm)) .expect("failed to decode canister module"); let embedder = WasmtimeEmbedder::new(config, no_op_logger()); diff --git a/rs/embedders/src/compilation_cache.rs b/rs/embedders/src/compilation_cache.rs index 2ef9a6cdf96..73f9f98d092 100644 --- a/rs/embedders/src/compilation_cache.rs +++ b/rs/embedders/src/compilation_cache.rs @@ -15,10 +15,12 @@ use crate::{ }; use ic_interfaces::execution_environment::{HypervisorError, HypervisorResult}; use ic_replicated_state::canister_state::execution_state::WasmMetadata; -use ic_types::{methods::WasmMethod, NumBytes, NumInstructions}; +use ic_types::{methods::WasmMethod, MemoryDiskBytes, NumBytes, NumInstructions}; use ic_utils_lru_cache::LruCache; use ic_wasm_types::{CanisterModule, WasmHash}; +const GB: u64 = 1024 * 1024 * 1024; + /// Stores the serialized modules of wasm code that has already been compiled so /// that it can be used again without recompiling. pub enum CompilationCache { @@ -36,10 +38,26 @@ pub enum CompilationCache { }, } +impl MemoryDiskBytes for CompilationCache { + fn memory_bytes(&self) -> usize { + match self { + CompilationCache::Memory { cache } => cache.lock().unwrap().memory_bytes(), + CompilationCache::Disk { cache, .. } => cache.lock().unwrap().memory_bytes(), + } + } + + fn disk_bytes(&self) -> usize { + match self { + CompilationCache::Memory { cache } => cache.lock().unwrap().disk_bytes(), + CompilationCache::Disk { cache, .. } => cache.lock().unwrap().disk_bytes(), + } + } +} + impl CompilationCache { pub fn new(capacity: NumBytes) -> Self { Self::Memory { - cache: Mutex::new(LruCache::new(capacity)), + cache: Mutex::new(LruCache::new(capacity, NumBytes::from(GB))), } } diff --git a/rs/embedders/src/serialized_module.rs b/rs/embedders/src/serialized_module.rs index db8f8954c15..41d99b7e7a9 100644 --- a/rs/embedders/src/serialized_module.rs +++ b/rs/embedders/src/serialized_module.rs @@ -10,7 +10,7 @@ use std::{ use ic_interfaces::execution_environment::{HypervisorError, HypervisorResult}; use ic_replicated_state::canister_state::execution_state::WasmMetadata; -use ic_types::{methods::WasmMethod, CountBytes, NumInstructions}; +use ic_types::{methods::WasmMethod, MemoryDiskBytes, NumInstructions}; use ic_wasm_types::WasmEngineError; use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use serde::{Deserialize, Serialize}; @@ -82,10 +82,14 @@ pub struct SerializedModule { pub is_wasm64: bool, } -impl CountBytes for SerializedModule { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for SerializedModule { + fn memory_bytes(&self) -> usize { self.bytes.0.len() } + + fn disk_bytes(&self) -> usize { + 0 + } } impl SerializedModule { @@ -147,10 +151,15 @@ pub struct OnDiskSerializedModule { pub is_wasm64: bool, } -impl CountBytes for OnDiskSerializedModule { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for OnDiskSerializedModule { + fn memory_bytes(&self) -> usize { std::mem::size_of::() } + + fn disk_bytes(&self) -> usize { + (self.bytes.metadata().unwrap().len() + self.initial_state_data.metadata().unwrap().len()) + as usize + } } impl OnDiskSerializedModule { diff --git a/rs/embedders/src/wasm_executor.rs b/rs/embedders/src/wasm_executor.rs index ec2de9f11be..e920683064e 100644 --- a/rs/embedders/src/wasm_executor.rs +++ b/rs/embedders/src/wasm_executor.rs @@ -385,6 +385,29 @@ impl WasmExecutorImpl { }) } else { match compilation_cache.get(&wasm_binary.binary) { + Some(Ok(StoredCompilation::Disk(on_disk_serialized_module))) => { + // This path is only used when sandboxing is disabled. + // Otherwise the fd is implicitly duplicated when passed to + // the sandbox process over the unix socket. + let instance_pre = self.wasm_embedder.read_file_and_pre_instantiate( + on_disk_serialized_module + .bytes + .try_clone() + .expect("Unable to duplicate serialzed module file descriptor."), + ); + let cache = EmbedderCache::new(instance_pre.clone()); + *guard = Some(cache.clone()); + match instance_pre { + Ok(_) => Ok(CacheLookup { + cache, + serialized_module: Some(StoredCompilation::Disk( + on_disk_serialized_module, + )), + compilation_result: None, + }), + Err(err) => Err(err), + } + } Some(Ok(StoredCompilation::Memory(serialized_module))) => { let instance_pre = self .wasm_embedder @@ -400,10 +423,6 @@ impl WasmExecutorImpl { Err(err) => Err(err), } } - Some(Ok(StoredCompilation::Disk(_serialized_module))) => { - // TODO(EXC-1780) - panic!("On disk compilation cache not yet supported"); - } Some(Err(err)) => { let cache: HypervisorResult = Err(err.clone()); *guard = Some(EmbedderCache::new(cache)); diff --git a/rs/embedders/src/wasm_utils.rs b/rs/embedders/src/wasm_utils.rs index 31e8b4ce0c5..771a5d328f3 100644 --- a/rs/embedders/src/wasm_utils.rs +++ b/rs/embedders/src/wasm_utils.rs @@ -133,6 +133,9 @@ impl Segments { // them into a map page_num -> page. Whenever we map a chunk into its page, // we simply copy its bytes to the right place inside the page. .fold(HashMap::new(), |mut acc, (offset, bytes)| { + if bytes.is_empty() { + return acc; + } let page_num = offset / PAGE_SIZE; let list = acc .entry(PageIndex::new(page_num as u64)) diff --git a/rs/embedders/src/wasmtime_embedder.rs b/rs/embedders/src/wasmtime_embedder.rs index b9c8dca7577..113ee053de4 100644 --- a/rs/embedders/src/wasmtime_embedder.rs +++ b/rs/embedders/src/wasmtime_embedder.rs @@ -11,8 +11,6 @@ use std::{ convert::TryFrom, fs::File, mem::size_of, - os::fd::{AsRawFd, IntoRawFd}, - os::unix::fs::MetadataExt, sync::{atomic::Ordering, Arc, Mutex}, }; @@ -39,7 +37,6 @@ use ic_types::{ }; use ic_wasm_types::{BinaryEncodedWasm, WasmEngineError}; use memory_tracker::{DirtyPageTracking, PageBitmap, SigsegvMemoryTracker}; -use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use signal_stack::WasmtimeSignalStack; use crate::wasm_utils::instrumentation::{ @@ -336,28 +333,18 @@ impl WasmtimeEmbedder { self.pre_instantiate(&module) } - /// TODO(EXC-1800): Replace this with `wasmtime::Module::deserialize_open_file`. - fn deserialize_from_file(&self, serialized_module: &File) -> HypervisorResult { - let mmap_size = serialized_module.metadata().unwrap().size() as usize; - let mmap_ptr = unsafe { - mmap( - std::ptr::null_mut(), - mmap_size, - ProtFlags::PROT_READ, - MapFlags::MAP_PRIVATE, - serialized_module.as_raw_fd(), - 0, - ) - } - .unwrap_or_else(|err| panic!("Module deserialization failed: {:?}", err)) - as *mut u8; - let bytes = unsafe { std::slice::from_raw_parts(mmap_ptr, mmap_size) }; + fn deserialize_from_file(&self, serialized_module: File) -> HypervisorResult { + // SAFETY: The compilation cache setup guarantees that this file is a + // valid serialized module and will not be modified after initial + // creation. unsafe { - Module::deserialize(&self.create_engine()?, bytes).map_err(|err| { - HypervisorError::WasmEngineError(WasmEngineError::FailedToDeserializeModule( - format!("{:?}", err), - )) - }) + Module::deserialize_open_file(&self.create_engine()?, serialized_module).map_err( + |err| { + HypervisorError::WasmEngineError(WasmEngineError::FailedToDeserializeModule( + format!("{:?}", err), + )) + }, + ) } } @@ -365,10 +352,7 @@ impl WasmtimeEmbedder { &self, serialized_module: File, ) -> HypervisorResult> { - // TODO(EXC-1800): Switch to new wasmtime API and remove leaking the - // file. - let module = self.deserialize_from_file(&serialized_module)?; - let _ = serialized_module.into_raw_fd(); + let module = self.deserialize_from_file(serialized_module)?; self.pre_instantiate(&module) } diff --git a/rs/embedders/tests/wasmtime_random_memory_writes.rs b/rs/embedders/tests/wasmtime_random_memory_writes.rs index 14eb3700fa0..beb4733dbcb 100644 --- a/rs/embedders/tests/wasmtime_random_memory_writes.rs +++ b/rs/embedders/tests/wasmtime_random_memory_writes.rs @@ -980,126 +980,90 @@ mod tests { #[test] fn test_proportional_instructions_consumption_to_data_size() { - with_test_replica_logger(|log| { - let subnet_type = SubnetType::Application; - let dst: u32 = 0; - - let dirty_heap_cost = match EmbeddersConfig::default().metering_type { - ic_config::embedders::MeteringType::New => SchedulerConfig::application_subnet() - .dirty_page_overhead - .get(), - _ => 0, - }; + for subnet_type in [ + SubnetType::Application, + SubnetType::VerifiedApplication, + SubnetType::System, + ] { + with_test_replica_logger(|log| { + let dst: u32 = 0; + + let dirty_heap_cost = match EmbeddersConfig::default().metering_type { + ic_config::embedders::MeteringType::New => match subnet_type { + SubnetType::System => { + SchedulerConfig::system_subnet().dirty_page_overhead.get() + } + SubnetType::Application => SchedulerConfig::application_subnet() + .dirty_page_overhead + .get(), + SubnetType::VerifiedApplication => { + SchedulerConfig::verified_application_subnet() + .dirty_page_overhead + .get() + } + }, + _ => 0, + }; - let mut payload: Vec = dst.to_le_bytes().to_vec(); - payload.extend(random_payload()); - let payload_size = payload.len() - 4; + let mut payload: Vec = dst.to_le_bytes().to_vec(); + payload.extend(random_payload()); + let payload_size = payload.len() - 4; - let mut double_size_payload: Vec = payload.clone(); - double_size_payload.extend(random_payload()); + let mut double_size_payload: Vec = payload.clone(); + double_size_payload.extend(random_payload()); - let (instructions_consumed_without_data, dry_run_stats) = run_and_get_stats( - log.clone(), - "write_bytes", - dst.to_le_bytes().to_vec(), - MAX_NUM_INSTRUCTIONS, - subnet_type, - ) - .unwrap(); - let dry_run_dirty_heap = dry_run_stats.wasm_dirty_pages.len() as u64; - - { - // Number of instructions consumed only for copying the payload. - let (consumed_instructions, run_stats) = run_and_get_stats( + let (instructions_consumed_without_data, dry_run_stats) = run_and_get_stats( log.clone(), "write_bytes", - payload, - MAX_NUM_INSTRUCTIONS, - subnet_type, - ) - .unwrap(); - let dirty_heap = run_stats.wasm_dirty_pages.len() as u64; - let consumed_instructions = - consumed_instructions - instructions_consumed_without_data; - assert_eq!( - (consumed_instructions.get() - dirty_heap * dirty_heap_cost) as usize, - (payload_size / BYTES_PER_INSTRUCTION) - - (dry_run_dirty_heap * dirty_heap_cost) as usize, - ); - } - - { - // Number of instructions consumed increased with the size of the data. - let (consumed_instructions, run_stats) = run_and_get_stats( - log, - "write_bytes", - double_size_payload, + dst.to_le_bytes().to_vec(), MAX_NUM_INSTRUCTIONS, subnet_type, ) .unwrap(); - let dirty_heap = run_stats.wasm_dirty_pages.len() as u64; - let consumed_instructions = - consumed_instructions - instructions_consumed_without_data; - - assert_eq!( - (consumed_instructions.get() - dirty_heap * dirty_heap_cost) as usize, - (2 * payload_size / BYTES_PER_INSTRUCTION) - - (dry_run_dirty_heap * dirty_heap_cost) as usize - ); - } - }) - } - - #[test] - fn test_no_instructions_consumption_based_on_data_size_on_system_subnet() { - with_test_replica_logger(|log| { - let subnet_type = SubnetType::System; - let dst: u32 = 0; - - let mut payload: Vec = dst.to_le_bytes().to_vec(); - payload.extend(random_payload()); - - let mut double_size_payload: Vec = payload.clone(); - double_size_payload.extend(random_payload()); - - let instructions_consumed_without_data = get_num_instructions_consumed( - log.clone(), - "write_bytes", - dst.to_le_bytes().to_vec(), - MAX_NUM_INSTRUCTIONS, - subnet_type, - ) - .unwrap(); - - { - // Number of instructions consumed for copying the payload is zero. - let consumed_instructions = get_num_instructions_consumed( - log.clone(), - "write_bytes", - payload, - MAX_NUM_INSTRUCTIONS, - subnet_type, - ) - .unwrap() - - instructions_consumed_without_data; - assert_eq!(consumed_instructions.get(), 0); - } + let dry_run_dirty_heap = dry_run_stats.wasm_dirty_pages.len() as u64; + + { + // Number of instructions consumed only for copying the payload. + let (consumed_instructions, run_stats) = run_and_get_stats( + log.clone(), + "write_bytes", + payload, + MAX_NUM_INSTRUCTIONS, + subnet_type, + ) + .unwrap(); + let dirty_heap = run_stats.wasm_dirty_pages.len() as u64; + let consumed_instructions = + consumed_instructions - instructions_consumed_without_data; + assert_eq!( + (consumed_instructions.get() - dirty_heap * dirty_heap_cost) as usize, + (payload_size / BYTES_PER_INSTRUCTION) + - (dry_run_dirty_heap * dirty_heap_cost) as usize, + ); + } - { - // Number of instructions consumed for copying the payload is zero. - let consumed_instructions = get_num_instructions_consumed( - log, - "write_bytes", - double_size_payload, - MAX_NUM_INSTRUCTIONS, - subnet_type, - ) - .unwrap() - - instructions_consumed_without_data; - assert_eq!(consumed_instructions.get(), 0); - } - }) + { + // Number of instructions consumed increased with the size of the data. + let (consumed_instructions, run_stats) = run_and_get_stats( + log, + "write_bytes", + double_size_payload, + MAX_NUM_INSTRUCTIONS, + subnet_type, + ) + .unwrap(); + let dirty_heap = run_stats.wasm_dirty_pages.len() as u64; + let consumed_instructions = + consumed_instructions - instructions_consumed_without_data; + + assert_eq!( + (consumed_instructions.get() - dirty_heap * dirty_heap_cost) as usize, + (2 * payload_size / BYTES_PER_INSTRUCTION) + - (dry_run_dirty_heap * dirty_heap_cost) as usize + ); + } + }) + } } fn run_and_get_stats( diff --git a/rs/execution_environment/fuzz/fuzz_targets/execute_system_api_call.rs b/rs/execution_environment/fuzz/fuzz_targets/execute_system_api_call.rs index de4b8439809..7b3e5f1414d 100644 --- a/rs/execution_environment/fuzz/fuzz_targets/execute_system_api_call.rs +++ b/rs/execution_environment/fuzz/fuzz_targets/execute_system_api_call.rs @@ -1,8 +1,4 @@ -use ic_config::{ - embedders::Config as EmbeddersConfig, embedders::FeatureFlags, - execution_environment::Config as ExecutionConfig, flag_status::FlagStatus, - subnet_config::SubnetConfig, -}; +use ic_config::{execution_environment::Config as ExecutionConfig, subnet_config::SubnetConfig}; use ic_management_canister_types::{CanisterInstallMode, CanisterSettingsArgsBuilder}; use ic_registry_subnet_type::SubnetType; use ic_state_machine_tests::{StateMachine, StateMachineBuilder, StateMachineConfig}; @@ -10,10 +6,11 @@ use ic_types::{CanisterId, Cycles, NumBytes}; use libfuzzer_sys::fuzz_target; use std::cell::RefCell; -use wasm_fuzzers::ic_wasm::ICWasmModule; +use wasm_fuzzers::ic_wasm::{ic_embedders_config, ICWasmModule}; thread_local! { - static ENV: RefCell<(StateMachine, CanisterId)> = RefCell::new(setup_env()); + static ENV_32: RefCell<(StateMachine, CanisterId)> = RefCell::new(setup_env(false)); + static ENV_64: RefCell<(StateMachine, CanisterId)> = RefCell::new(setup_env(true)); } const HELLO_WORLD_WAT: &str = r#" @@ -30,7 +27,7 @@ fn main() { } fuzz_target!(|data: ICWasmModule| { - with_env(|env, canister_id| { + with_env(data.config.memory64_enabled, |env, canister_id| { let wasm = data.module.to_bytes(); if env .install_wasm_in_mode(*canister_id, CanisterInstallMode::Reinstall, wasm, vec![]) @@ -44,29 +41,29 @@ fuzz_target!(|data: ICWasmModule| { }); }); -fn with_env(f: F) -> R +fn with_env(memory64_enabled: bool, f: F) -> R where F: FnOnce(&StateMachine, &CanisterId) -> R, { - ENV.with(|env| { - let env_ref = env.borrow(); - f(&env_ref.0, &env_ref.1) // Pass references to the closure - }) + if memory64_enabled { + ENV_64.with(|env| { + let env_ref = env.borrow(); + f(&env_ref.0, &env_ref.1) + }) + } else { + ENV_32.with(|env| { + let env_ref = env.borrow(); + f(&env_ref.0, &env_ref.1) + }) + } } // A setup function to initialize StateMachine with a dummy canister and expose the cansiter_id. // The same canister_id and StateMachine reference is used in the fuzzing runs, where the // canister is reinstalled under the same canister_id -fn setup_env() -> (StateMachine, CanisterId) { +fn setup_env(memory64_enabled: bool) -> (StateMachine, CanisterId) { let exec_config = ExecutionConfig { - embedders_config: EmbeddersConfig { - feature_flags: FeatureFlags { - write_barrier: FlagStatus::Enabled, - wasm64: FlagStatus::Enabled, // Enable wasm64 to match generated ICWasmModule. - ..Default::default() - }, - ..Default::default() - }, + embedders_config: ic_embedders_config(memory64_enabled), max_compilation_cache_size: NumBytes::new(10 * 1024 * 1024), // 10MiB ..Default::default() }; diff --git a/rs/execution_environment/src/execution/update/tests.rs b/rs/execution_environment/src/execution/update/tests.rs index f8673ace1e6..2cd76a57e7e 100644 --- a/rs/execution_environment/src/execution/update/tests.rs +++ b/rs/execution_environment/src/execution/update/tests.rs @@ -3,7 +3,6 @@ use std::time::Duration; use assert_matches::assert_matches; use ic_base_types::NumSeconds; -use ic_config::subnet_config::SchedulerConfig; use ic_error_types::ErrorCode; use ic_interfaces::execution_environment::SubnetAvailableMemory; use ic_registry_subnet_type::SubnetType; @@ -352,7 +351,7 @@ fn dts_update_concurrent_cycles_change_fails() { } #[test] -fn dirty_pages_are_free_on_system_subnet() { +fn dirty_pages_cost_the_same_on_app_and_system_subnets() { fn instructions_to_write_stable_byte(mut test: ExecutionTest) -> NumInstructions { let initial_cycles = Cycles::new(1_000_000_000_000); let a_id = test.universal_canister_with_cycles(initial_cycles).unwrap(); @@ -376,12 +375,7 @@ fn dirty_pages_are_free_on_system_subnet() { .build(); let app_instructions = instructions_to_write_stable_byte(app_test); - // Can't check for equality because there are other charges that are omitted - // on system subnets. - assert!( - app_instructions - > system_instructions + SchedulerConfig::application_subnet().dirty_page_overhead - ); + assert_eq!(app_instructions, system_instructions); } #[test] diff --git a/rs/execution_environment/src/hypervisor.rs b/rs/execution_environment/src/hypervisor.rs index 6bbc702b7aa..4e472eff012 100644 --- a/rs/execution_environment/src/hypervisor.rs +++ b/rs/execution_environment/src/hypervisor.rs @@ -21,11 +21,11 @@ use ic_replicated_state::{NetworkTopology, ReplicatedState}; use ic_system_api::ExecutionParameters; use ic_system_api::{sandbox_safe_system_state::SandboxSafeSystemState, ApiType}; use ic_types::{ - messages::RequestMetadata, methods::FuncRef, CanisterId, NumBytes, NumInstructions, SubnetId, - Time, + messages::RequestMetadata, methods::FuncRef, CanisterId, MemoryDiskBytes, NumBytes, + NumInstructions, SubnetId, Time, }; use ic_wasm_types::CanisterModule; -use prometheus::{Histogram, HistogramVec, IntCounter, IntGauge}; +use prometheus::{Histogram, HistogramVec, IntCounter, IntGauge, IntGaugeVec}; use std::{ path::{Path, PathBuf}, sync::Arc, @@ -50,6 +50,7 @@ pub struct HypervisorMetrics { mmap_count: HistogramVec, mprotect_count: HistogramVec, copy_page_count: HistogramVec, + compilation_cache_size: IntGaugeVec, } impl HypervisorMetrics { @@ -124,6 +125,8 @@ impl HypervisorMetrics { decimal_buckets_with_zero(0,8), &["api_type", "memory_type"] ), + compilation_cache_size: metrics_registry.int_gauge_vec("hypervisor_compilation_cache_size", "Bytes in memory and on disk used by the compilation cache.", &["location"], + ), } } @@ -184,7 +187,12 @@ impl HypervisorMetrics { } } - fn observe_compilation_metrics(&self, compilation_result: &CompilationResult) { + fn observe_compilation_metrics( + &self, + compilation_result: &CompilationResult, + cache_memory_size: usize, + cache_disk_size: usize, + ) { let CompilationResult { largest_function_instruction_count, compilation_time, @@ -194,6 +202,12 @@ impl HypervisorMetrics { .observe(largest_function_instruction_count.get() as f64); self.compile.observe(compilation_time.as_secs_f64()); self.max_complexity.observe(*max_complexity as f64); + self.compilation_cache_size + .with_label_values(&["memory"]) + .set(cache_memory_size as i64); + self.compilation_cache_size + .with_label_values(&["disk"]) + .set(cache_disk_size as i64); } } @@ -255,8 +269,11 @@ impl Hypervisor { match creation_result { Ok((execution_state, compilation_cost, compilation_result)) => { if let Some(compilation_result) = compilation_result { - self.metrics - .observe_compilation_metrics(&compilation_result); + self.metrics.observe_compilation_metrics( + &compilation_result, + self.compilation_cache.memory_bytes(), + self.compilation_cache.disk_bytes(), + ); } round_limits.instructions -= as_round_instructions( compilation_cost_handling.adjusted_compilation_cost(compilation_cost), @@ -489,8 +506,11 @@ impl Hypervisor { execution_state, ); if let Some(compilation_result) = compilation_result { - self.metrics - .observe_compilation_metrics(&compilation_result); + self.metrics.observe_compilation_metrics( + &compilation_result, + self.compilation_cache.memory_bytes(), + self.compilation_cache.disk_bytes(), + ); } self.metrics.observe(&execution_result, api_type_str); diff --git a/rs/execution_environment/src/query_handler/query_cache.rs b/rs/execution_environment/src/query_handler/query_cache.rs index 0c6a1752998..43dcecc809b 100644 --- a/rs/execution_environment/src/query_handler/query_cache.rs +++ b/rs/execution_environment/src/query_handler/query_cache.rs @@ -8,7 +8,7 @@ use ic_types::{ batch::QueryStats, ingress::WasmResult, messages::{Query, QuerySource}, - CountBytes, Cycles, PrincipalId, Time, UserId, + Cycles, MemoryDiskBytes, PrincipalId, Time, UserId, }; use ic_utils_lru_cache::LruCache; use prometheus::{Histogram, IntCounter, IntGauge}; @@ -140,10 +140,14 @@ pub(crate) struct EntryKey { pub method_payload: Vec, } -impl CountBytes for EntryKey { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for EntryKey { + fn memory_bytes(&self) -> usize { size_of_val(self) + self.method_name.len() + self.method_payload.len() } + + fn disk_bytes(&self) -> usize { + 0 + } } impl From<&Query> for EntryKey { @@ -211,9 +215,13 @@ pub(crate) struct EntryValue { ignore_canister_balances: bool, } -impl CountBytes for EntryValue { - fn count_bytes(&self) -> usize { - size_of_val(self) + self.result.count_bytes() +impl MemoryDiskBytes for EntryValue { + fn memory_bytes(&self) -> usize { + size_of_val(self) + self.result.memory_bytes() + } + + fn disk_bytes(&self) -> usize { + 0 } } @@ -377,9 +385,13 @@ pub(crate) struct QueryCache { pub(crate) metrics: QueryCacheMetrics, } -impl CountBytes for QueryCache { - fn count_bytes(&self) -> usize { - size_of_val(self) + self.cache.lock().unwrap().count_bytes() +impl MemoryDiskBytes for QueryCache { + fn memory_bytes(&self) -> usize { + size_of_val(self) + self.cache.lock().unwrap().memory_bytes() + } + + fn disk_bytes(&self) -> usize { + 0 } } @@ -392,7 +404,7 @@ impl QueryCache { data_certificate_expiry_time: Duration, ) -> Self { QueryCache { - cache: Mutex::new(LruCache::new(capacity)), + cache: Mutex::new(LruCache::new(capacity, NumBytes::from(0))), max_expiry_time, data_certificate_expiry_time, metrics: QueryCacheMetrics::new(metrics_registry), @@ -422,7 +434,7 @@ impl QueryCache { // The cache entry is no longer valid, remove it. cache.pop(key); // Update the `count_bytes` metric. - self.metrics.count_bytes.set(cache.count_bytes() as i64); + self.metrics.count_bytes.set(cache.memory_bytes() as i64); } } None @@ -470,8 +482,8 @@ impl QueryCache { let d = evicted_value.elapsed_seconds(now); self.metrics.evicted_entries_duration.observe(d); } - let count_bytes = cache.count_bytes() as i64; - self.metrics.count_bytes.set(count_bytes); + let memory_bytes = cache.memory_bytes() as i64; + self.metrics.count_bytes.set(memory_bytes); self.metrics.len.set(cache.len() as i64); } } diff --git a/rs/execution_environment/src/query_handler/query_cache/tests.rs b/rs/execution_environment/src/query_handler/query_cache/tests.rs index 009c6beb9d9..45a74ced43c 100644 --- a/rs/execution_environment/src/query_handler/query_cache/tests.rs +++ b/rs/execution_environment/src/query_handler/query_cache/tests.rs @@ -16,7 +16,7 @@ use ic_types::{ batch::QueryStats, ingress::WasmResult, messages::{CanisterTask, Query, QuerySource}, - time, CountBytes, + time, MemoryDiskBytes, }; use ic_types_test_utils::ids::subnet_test_id; use ic_universal_canister::call_args; @@ -166,7 +166,7 @@ fn query_cache_reports_hits_and_misses_metrics() { } #[test] -fn query_cache_reports_evicted_entries_and_count_bytes_metrics() { +fn query_cache_reports_evicted_entries_and_memory_bytes_metrics() { const QUERY_CACHE_SIZE: usize = 2; /// Includes some room for the keys, headers etc. const QUERY_CACHE_CAPACITY: usize = REPLY_SIZE * (QUERY_CACHE_SIZE + 1); @@ -202,16 +202,16 @@ fn query_cache_reports_evicted_entries_and_count_bytes_metrics() { ); assert_eq!(0, m.invalidated_entries.get()); - let count_bytes = m.count_bytes.get() as usize; + let memory_bytes = m.count_bytes.get() as usize; // We can't match the size exactly, as it includes the key and the captured environment. // But we can assert that the sum of the sizes should be: - // REPLY_SIZE < count_bytes < REPLY_SIZE * 2 - assert!(REPLY_SIZE < count_bytes); - assert!(REPLY_SIZE * 2 * QUERY_CACHE_SIZE > count_bytes); + // REPLY_SIZE < memory_bytes < REPLY_SIZE * 2 + assert!(REPLY_SIZE < memory_bytes); + assert!(REPLY_SIZE * 2 * QUERY_CACHE_SIZE > memory_bytes); } #[test] -fn query_cache_reports_count_bytes_metric_on_invalidation() { +fn query_cache_reports_memory_bytes_metric_on_invalidation() { let mut test = builder_with_query_caching().build(); let a_id = test.universal_canister().unwrap(); let key = EntryKey { @@ -225,8 +225,8 @@ fn query_cache_reports_count_bytes_metric_on_invalidation() { let m = query_cache_metrics(&test); assert_eq!(0, m.hits.get()); assert_eq!(0, m.misses.get()); - let initial_count_bytes = m.count_bytes.get(); - assert!((initial_count_bytes as usize) < BIG_REPLY_SIZE); + let initial_memory_bytes = m.count_bytes.get(); + assert!((initial_memory_bytes as usize) < BIG_REPLY_SIZE); // Push a big result into the cache. let big_result = Ok(WasmResult::Reply(vec![0; BIG_REPLY_SIZE])); @@ -243,8 +243,8 @@ fn query_cache_reports_count_bytes_metric_on_invalidation() { ); assert_eq!(0, m.hits.get()); assert_eq!(1, m.misses.get()); - let count_bytes = m.count_bytes.get(); - assert!(((count_bytes - initial_count_bytes) as usize) > BIG_REPLY_SIZE); + let memory_bytes = m.count_bytes.get(); + assert!(((memory_bytes - initial_memory_bytes) as usize) > BIG_REPLY_SIZE); // Bump up the version test.canister_state_mut(a_id).system_state.canister_version += 1; @@ -255,8 +255,8 @@ fn query_cache_reports_count_bytes_metric_on_invalidation() { let m = query_cache_metrics(&test); assert_eq!(0, m.hits.get()); assert_eq!(1, m.misses.get()); - let final_count_bytes = m.count_bytes.get(); - assert!((final_count_bytes as usize) < BIG_REPLY_SIZE); + let final_memory_bytes = m.count_bytes.get(); + assert!((final_memory_bytes as usize) < BIG_REPLY_SIZE); } #[test] @@ -765,18 +765,18 @@ fn query_cache_frees_memory_after_invalidated_entries() { .build(); let id = test.canister_from_wat(QUERY_CACHE_WAT).unwrap(); - let count_bytes = query_cache(&test).count_bytes(); + let memory_bytes = query_cache(&test).memory_bytes(); // Initially the cache should be empty, i.e. less than 1MB. - assert!(count_bytes < BIG_RESPONSE_SIZE); + assert!(memory_bytes < BIG_RESPONSE_SIZE); // The 1MB result will be cached internally. let res = test .non_replicated_query(id, "canister_balance_sized_reply", vec![]) .unwrap(); - assert_eq!(BIG_RESPONSE_SIZE, res.count_bytes()); - let count_bytes = query_cache(&test).count_bytes(); + assert_eq!(BIG_RESPONSE_SIZE, res.memory_bytes()); + let memory_bytes = query_cache(&test).memory_bytes(); // After the first reply, the cache should have more than 1MB of data. - assert!(count_bytes > BIG_RESPONSE_SIZE); + assert!(memory_bytes > BIG_RESPONSE_SIZE); // Set the canister balance to 42, so the second reply will have just 42 bytes. test.canister_state_mut(id).system_state.remove_cycles( @@ -788,11 +788,11 @@ fn query_cache_frees_memory_after_invalidated_entries() { let res = test .non_replicated_query(id, "canister_balance_sized_reply", vec![]) .unwrap(); - assert_eq!(SMALL_RESPONSE_SIZE, res.count_bytes()); - let count_bytes = query_cache(&test).count_bytes(); + assert_eq!(SMALL_RESPONSE_SIZE, res.memory_bytes()); + let memory_bytes = query_cache(&test).memory_bytes(); // The second 42 reply should invalidate and replace the first 1MB reply in the cache. - assert!(count_bytes > SMALL_RESPONSE_SIZE); - assert!(count_bytes < BIG_RESPONSE_SIZE); + assert!(memory_bytes > SMALL_RESPONSE_SIZE); + assert!(memory_bytes < BIG_RESPONSE_SIZE); } #[test] @@ -803,8 +803,8 @@ fn query_cache_respects_cache_capacity() { let id = test.universal_canister().unwrap(); // Initially the cache should be empty, i.e. less than REPLY_SIZE. - let count_bytes = query_cache(&test).count_bytes(); - assert!(count_bytes < REPLY_SIZE); + let memory_bytes = query_cache(&test).memory_bytes(); + assert!(memory_bytes < REPLY_SIZE); // All replies should hit the same cache entry. for _ in 0..ITERATIONS { @@ -812,9 +812,9 @@ fn query_cache_respects_cache_capacity() { let _res = test.non_replicated_query(id, "query", wasm().reply_data(&[1; REPLY_SIZE / 2]).build()); // Now there should be only one reply in the cache. - let count_bytes = query_cache(&test).count_bytes(); - assert!(count_bytes > REPLY_SIZE); - assert!(count_bytes < QUERY_CACHE_CAPACITY); + let memory_bytes = query_cache(&test).memory_bytes(); + assert!(memory_bytes > REPLY_SIZE); + assert!(memory_bytes < QUERY_CACHE_CAPACITY); } // Now the replies should hit another entry. @@ -822,9 +822,9 @@ fn query_cache_respects_cache_capacity() { let _res = test.non_replicated_query(id, "query", wasm().reply_data(&[2; REPLY_SIZE / 2]).build()); // Now there should be two replies in the cache. - let count_bytes = query_cache(&test).count_bytes(); - assert!(count_bytes > REPLY_SIZE * 2); - assert!(count_bytes < QUERY_CACHE_CAPACITY); + let memory_bytes = query_cache(&test).memory_bytes(); + assert!(memory_bytes > REPLY_SIZE * 2); + assert!(memory_bytes < QUERY_CACHE_CAPACITY); } // Now the replies should evict the first entry. @@ -832,9 +832,9 @@ fn query_cache_respects_cache_capacity() { let _res = test.non_replicated_query(id, "query", wasm().reply_data(&[3; REPLY_SIZE / 2]).build()); // There should be still just two replies in the cache. - let count_bytes = query_cache(&test).count_bytes(); - assert!(count_bytes > REPLY_SIZE * 2); - assert!(count_bytes < QUERY_CACHE_CAPACITY); + let memory_bytes = query_cache(&test).memory_bytes(); + assert!(memory_bytes > REPLY_SIZE * 2); + assert!(memory_bytes < QUERY_CACHE_CAPACITY); } } @@ -844,13 +844,13 @@ fn query_cache_works_with_zero_cache_capacity() { let id = test.universal_canister().unwrap(); // Even with zero capacity the cache data structure uses some bytes for the pointers etc. - let initial_count_bytes = query_cache(&test).count_bytes(); + let initial_memory_bytes = query_cache(&test).memory_bytes(); // Replies should not change the initial (zero) capacity. for _ in 0..ITERATIONS { let _res = test.non_replicated_query(id, "query", wasm().reply_data(&[1]).build()); - let count_bytes = query_cache(&test).count_bytes(); - assert_eq!(initial_count_bytes, count_bytes); + let memory_bytes = query_cache(&test).memory_bytes(); + assert_eq!(initial_memory_bytes, memory_bytes); } } diff --git a/rs/execution_environment/tests/execution_test.rs b/rs/execution_environment/tests/execution_test.rs index 68031280b6f..f8cae43c080 100644 --- a/rs/execution_environment/tests/execution_test.rs +++ b/rs/execution_environment/tests/execution_test.rs @@ -1,5 +1,6 @@ use assert_matches::assert_matches; use candid::Encode; +use canister_test::CanisterInstallMode; use ic_base_types::PrincipalId; use ic_config::{ execution_environment::{Config as HypervisorConfig, DEFAULT_WASM_MEMORY_LIMIT}, @@ -2773,3 +2774,36 @@ fn do_not_initialize_wasm_memory_limit_if_it_is_not_empty() { let wasm_memory_limit = fetch_wasm_memory_limit(&env, canister_id); assert_eq!(wasm_memory_limit, NumBytes::new(10_000_000_000)); } + +/// Even if a Wasm module has inital memory size 0, it is allowed to have data +/// segments of length 0 inserted at address 0. This test checks that such data +/// segments don't trigger any of our critical errors. +#[test] +fn no_critical_error_on_empty_data_segment() { + let env = StateMachine::new(); + let wat: &str = r#" + (module + (memory (;0;) i64 0) + (data (;0;) (i64.const 0) "") + ) + "#; + let _id = env.install_canister_wat(wat, vec![], None); + + // A module with an empty data segment outside of memory should fail to + // install, but not trigger any critical errors. + let wat: &str = r#" + (module + (memory (;0;) i64 0) + (data (;0;) (i64.const 1) "") + ) + "#; + let wasm = wat::parse_str(wat).unwrap(); + let id = env.create_canister(None); + let error = env + .install_wasm_in_mode(id, CanisterInstallMode::Install, wasm, vec![]) + .unwrap_err(); + error.assert_contains( + ErrorCode::CanisterInvalidWasm, + "Wasm module has invalid data segment of 0 bytes at 1.", + ); +} diff --git a/rs/execution_environment/tests/storage_reservation.rs b/rs/execution_environment/tests/storage_reservation.rs index 8c9e4598235..d60bbc77211 100644 --- a/rs/execution_environment/tests/storage_reservation.rs +++ b/rs/execution_environment/tests/storage_reservation.rs @@ -1,5 +1,6 @@ use ic_config::execution_environment::Config as ExecutionConfig; use ic_config::subnet_config::SubnetConfig; +use ic_error_types::ErrorCode; use ic_management_canister_types::TakeCanisterSnapshotArgs; use ic_management_canister_types::{self as ic00, CanisterInstallMode, EmptyBlob, Payload}; use ic_registry_subnet_type::SubnetType; @@ -168,3 +169,43 @@ fn test_storage_reservation_triggered_in_canister_snapshot_with_enough_cycles_av reserved_balance_before_snapshot ); } + +#[test] +fn test_storage_reservation_triggered_in_canister_snapshot_without_enough_cycles_available() { + // This test verifies that a canister cannot take a snapshot if it does not have enough + // cycles to cover the storage reservation triggered by the snapshot operation. The main + // point of the test is to verify that the error message is informative and includes the + // amount of cycles required to cover the storage reservation. + // + // The error message is produced by running the test once and checking the output. Calculating + // the exact amounts is hard to do in advance. Note that any changes to cycles cost or how + // the reservation mechanism works may require updating the error message in the test. + + let (env, canister_id) = setup( + SUBNET_MEMORY_THRESHOLD, + SUBNET_MEMORY_CAPACITY, + Some(300_400_000_000), + ); + assert_eq!(reserved_balance(&env, canister_id), 0); + + // Grow memory in update call, should trigger storage reservation. + let _ = env.execute_ingress(canister_id, "update", wasm().stable_grow(3000).build()); + let reserved_balance_before_snapshot = reserved_balance(&env, canister_id); + assert_gt!(reserved_balance_before_snapshot, 0); // Storage reservation is triggered. + + // Take a snapshot to trigger more storage reservation. The canister does not have + // enough cycles in its balance, so this should fail. + let res = env.take_canister_snapshot(TakeCanisterSnapshotArgs::new(canister_id, None)); + match res { + Ok(_) => panic!("Expected an error but got Ok(_)"), + Err(err) => { + assert_eq!(err.code(), ErrorCode::InsufficientCyclesInMemoryGrow); + // Match on a substring of the error message. Due to a difference in instructions consumed on + // Mac vs Linux, we cannot match on the exact number of cycles but we only need to verify it's + // a non-zero amount. + assert!(err + .description() + .contains("due to insufficient cycles. At least 339_603_")); + } + } +} diff --git a/rs/http_endpoints/public/src/call.rs b/rs/http_endpoints/public/src/call.rs index a02984f6a5d..d2a3a1bc3f1 100644 --- a/rs/http_endpoints/public/src/call.rs +++ b/rs/http_endpoints/public/src/call.rs @@ -251,7 +251,7 @@ impl IngressValidator { message: "".into(), })? .map_err(|validation_error| { - validation_error_to_http_error(message_id, validation_error, &log) + validation_error_to_http_error(msg.as_ref(), validation_error, &log) })?; let ingress_filter = ingress_filter.lock().unwrap().clone(); diff --git a/rs/http_endpoints/public/src/common.rs b/rs/http_endpoints/public/src/common.rs index 1f40f4c7e35..60d34d92d35 100644 --- a/rs/http_endpoints/public/src/common.rs +++ b/rs/http_endpoints/public/src/common.rs @@ -20,7 +20,7 @@ use ic_replicated_state::ReplicatedState; use ic_types::{ crypto::threshold_sig::ThresholdSigPublicKey, malicious_flags::MaliciousFlags, - messages::{HttpRequest, HttpRequestContent, MessageId}, + messages::{HttpRequest, HttpRequestContent}, RegistryVersion, SubnetId, Time, }; use ic_validator::{ @@ -246,12 +246,22 @@ impl IntoResponse for CborUserError { } } -pub(crate) fn validation_error_to_http_error( - message_id: MessageId, +pub(crate) fn validation_error_to_http_error( + request: &HttpRequest, err: RequestValidationError, log: &ReplicaLogger, ) -> HttpError { - info!(log, "msg_id: {}, err: {}", message_id, err); + let message_id = request.id(); + match err { + RequestValidationError::InvalidSignature(_) => { + info!( + log, + "msg_id: {}, err: {}, request: {:?}", message_id, err, request + ) + } + _ => info!(log, "msg_id: {}, err: {}", message_id, err), + } + HttpError { status: StatusCode::BAD_REQUEST, message: format!("{err}"), diff --git a/rs/http_endpoints/public/src/query.rs b/rs/http_endpoints/public/src/query.rs index a68bdcceeb4..27bc9b465b1 100644 --- a/rs/http_endpoints/public/src/query.rs +++ b/rs/http_endpoints/public/src/query.rs @@ -194,7 +194,7 @@ pub(crate) async fn query( { Ok(Ok(_)) => {} Ok(Err(err)) => { - let http_err = validation_error_to_http_error(request.id(), err, &log); + let http_err = validation_error_to_http_error(&request, err, &log); return (http_err.status, http_err.message).into_response(); } Err(_) => { diff --git a/rs/http_endpoints/public/src/read_state/canister.rs b/rs/http_endpoints/public/src/read_state/canister.rs index 1a491c8f036..1a9f191695b 100644 --- a/rs/http_endpoints/public/src/read_state/canister.rs +++ b/rs/http_endpoints/public/src/read_state/canister.rs @@ -169,7 +169,7 @@ pub(crate) async fn canister_read_state( match validator.validate_request(&request_c, current_time(), &root_of_trust_provider) { Ok(targets) => targets, Err(err) => { - let http_err = validation_error_to_http_error(request.id(), err, &log); + let http_err = validation_error_to_http_error(&request, err, &log); return (http_err.status, http_err.message).into_response(); } }; diff --git a/rs/interfaces/src/execution_environment/errors.rs b/rs/interfaces/src/execution_environment/errors.rs index 765d808b496..073967a0323 100644 --- a/rs/interfaces/src/execution_environment/errors.rs +++ b/rs/interfaces/src/execution_environment/errors.rs @@ -1,6 +1,6 @@ use ic_base_types::{NumBytes, PrincipalIdBlobParseError}; use ic_error_types::UserError; -use ic_types::{methods::WasmMethod, CanisterId, CountBytes, Cycles, NumInstructions}; +use ic_types::{methods::WasmMethod, CanisterId, Cycles, MemoryDiskBytes, NumInstructions}; use ic_wasm_types::{ doc_ref, AsErrorHelp, ErrorHelp, WasmEngineError, WasmInstrumentationError, WasmValidationError, }; @@ -385,10 +385,14 @@ impl std::fmt::Display for HypervisorError { } } -impl CountBytes for HypervisorError { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for HypervisorError { + fn memory_bytes(&self) -> usize { std::mem::size_of::() } + + fn disk_bytes(&self) -> usize { + 0 + } } impl AsErrorHelp for HypervisorError { diff --git a/rs/ledger_suite/icp/index/BUILD.bazel b/rs/ledger_suite/icp/index/BUILD.bazel index cef900eb663..7c11c0c3a05 100644 --- a/rs/ledger_suite/icp/index/BUILD.bazel +++ b/rs/ledger_suite/icp/index/BUILD.bazel @@ -79,7 +79,10 @@ rust_test( rust_test( name = "ic_icp_index_canister_test", crate = ":_wasm_ic-icp-index-canister", - data = [":index.did"], + data = [ + ":index.did", + "//rs/ledger_suite/icp:ledger.did", + ], env = { "CARGO_MANIFEST_DIR": "rs/ledger_suite/icp/index", }, @@ -102,7 +105,6 @@ rust_ic_test( "LEDGER_CANISTER_NOTIFY_METHOD_WASM_PATH": "$(rootpath //rs/ledger_suite/icp/ledger:ledger-canister-wasm-notify-method)", "LEDGER_CANISTER_WASM_PATH": "$(rootpath //rs/ledger_suite/icp/ledger:ledger-canister-wasm)", }, - flaky = True, tags = ["cpu:4"], deps = [":ic-icp-index"] + DEPENDENCIES + DEV_DEPENDENCIES, ) diff --git a/rs/ledger_suite/icp/index/src/main.rs b/rs/ledger_suite/icp/index/src/main.rs index 0867d6ab041..a14dee429f9 100644 --- a/rs/ledger_suite/icp/index/src/main.rs +++ b/rs/ledger_suite/icp/index/src/main.rs @@ -751,3 +751,38 @@ fn check_candid_interface_compatibility() { ) .unwrap(); } + +#[test] +fn check_index_and_ledger_encoded_block_compatibility() { + // check that ledger.did and index.did agree on the encoded block format + let manifest_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); + let ledger_did_file = manifest_dir.join("../ledger.did"); + let index_did_file = manifest_dir.join("./index.did"); + let mut ledger_env = candid_parser::utils::CandidSource::File(ledger_did_file.as_path()) + .load() + .unwrap() + .0; + let index_env = candid_parser::utils::CandidSource::File(index_did_file.as_path()) + .load() + .unwrap() + .0; + let ledger_encoded_block_response_type = ledger_env + .find_type("QueryEncodedBlocksResponse") + .unwrap() + .to_owned(); + let index_encoded_block_response_type = + index_env.find_type("GetBlocksResponse").unwrap().to_owned(); + + let mut gamma = std::collections::HashSet::new(); + let index_encoded_block_response_type = + ledger_env.merge_type(index_env, index_encoded_block_response_type.clone()); + // Check if the ledger `query_encoded_blocks` response <: the index `get_blocks` response, + // i.e., if the index response type is a subtype of the ledger response type. + candid::types::subtype::subtype( + &mut gamma, + &ledger_env, + &ledger_encoded_block_response_type, + &index_encoded_block_response_type, + ) + .expect("Ledger and Index encoded block types are different"); +} diff --git a/rs/ledger_suite/icp/ledger/BUILD.bazel b/rs/ledger_suite/icp/ledger/BUILD.bazel index 0d9bea50cb9..ffe62605d7f 100644 --- a/rs/ledger_suite/icp/ledger/BUILD.bazel +++ b/rs/ledger_suite/icp/ledger/BUILD.bazel @@ -129,7 +129,6 @@ rust_ic_test( "LEDGER_CANISTER_NEXT_VERSION_WASM_PATH": "$(rootpath :ledger-canister-wasm-next-version)", "LEDGER_CANISTER_LOW_LIMITS_WASM_PATH": "$(rootpath :ledger-canister-wasm-low-limits)", }, - flaky = True, tags = ["cpu:4"], deps = [ # Keep sorted. diff --git a/rs/ledger_suite/icrc1/archive/BUILD.bazel b/rs/ledger_suite/icrc1/archive/BUILD.bazel index d21998270ec..b6db17976c0 100644 --- a/rs/ledger_suite/icrc1/archive/BUILD.bazel +++ b/rs/ledger_suite/icrc1/archive/BUILD.bazel @@ -56,6 +56,7 @@ rust_test( crate = ":_wasm_archive_canister", data = [ ":archive.did", + "//rs/ledger_suite/icrc1/ledger:ledger.did", ], env = { "CARGO_MANIFEST_DIR": "rs/ledger_suite/icrc1/archive", diff --git a/rs/ledger_suite/icrc1/archive/src/main.rs b/rs/ledger_suite/icrc1/archive/src/main.rs index a8d8eb3c5e1..f629929c889 100644 --- a/rs/ledger_suite/icrc1/archive/src/main.rs +++ b/rs/ledger_suite/icrc1/archive/src/main.rs @@ -436,3 +436,31 @@ fn check_candid_interface() { ) .expect("the ledger interface is not compatible with archive.did"); } + +#[test] +fn check_archive_and_ledger_block_equality() { + // check that ledger.did and archive.did agree on the block format + let manifest_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); + let ledger_did_file = manifest_dir.join("../ledger/ledger.did"); + let archive_did_file = manifest_dir.join("archive.did"); + let mut ledger_env = candid_parser::utils::CandidSource::File(ledger_did_file.as_path()) + .load() + .unwrap() + .0; + let archive_env = candid_parser::utils::CandidSource::File(archive_did_file.as_path()) + .load() + .unwrap() + .0; + let ledger_block_type = ledger_env.find_type("Block").unwrap().to_owned(); + let archive_block_type = archive_env.find_type("Block").unwrap().to_owned(); + + let mut gamma = std::collections::HashSet::new(); + let archive_block_type = ledger_env.merge_type(archive_env, archive_block_type.clone()); + candid::types::subtype::equal( + &mut gamma, + &ledger_env, + &ledger_block_type, + &archive_block_type, + ) + .expect("Ledger and Archive block types are different"); +} diff --git a/rs/ledger_suite/icrc1/index-ng/BUILD.bazel b/rs/ledger_suite/icrc1/index-ng/BUILD.bazel index 832eb1a3c60..1c80cd0f10c 100644 --- a/rs/ledger_suite/icrc1/index-ng/BUILD.bazel +++ b/rs/ledger_suite/icrc1/index-ng/BUILD.bazel @@ -79,7 +79,10 @@ rust_library( rust_test( name = "index_ng_unit_test", crate = ":_wasm_index_ng_canister", - data = [":index-ng.did"], + data = [ + ":index-ng.did", + "//rs/ledger_suite/icrc1/ledger:ledger.did", + ], deps = [ # Keep sorted. "//rs/ledger_suite/icrc1/test_utils", diff --git a/rs/ledger_suite/icrc1/index-ng/src/main.rs b/rs/ledger_suite/icrc1/index-ng/src/main.rs index 644cd22bdaf..66cd8a876ee 100644 --- a/rs/ledger_suite/icrc1/index-ng/src/main.rs +++ b/rs/ledger_suite/icrc1/index-ng/src/main.rs @@ -1204,3 +1204,31 @@ fn check_candid_interface() { ) }); } + +#[test] +fn check_index_and_ledger_block_equality() { + // check that ledger.did and index-ng.did agree on the block format + let manifest_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); + let ledger_did_file = manifest_dir.join("../ledger/ledger.did"); + let index_did_file = manifest_dir.join("index-ng.did"); + let mut ledger_env = candid_parser::utils::CandidSource::File(ledger_did_file.as_path()) + .load() + .unwrap() + .0; + let index_env = candid_parser::utils::CandidSource::File(index_did_file.as_path()) + .load() + .unwrap() + .0; + let ledger_block_type = ledger_env.find_type("Block").unwrap().to_owned(); + let index_block_type = index_env.find_type("Block").unwrap().to_owned(); + + let mut gamma = std::collections::HashSet::new(); + let index_block_type = ledger_env.merge_type(index_env, index_block_type.clone()); + candid::types::subtype::equal( + &mut gamma, + &ledger_env, + &ledger_block_type, + &index_block_type, + ) + .expect("Ledger and Index block types are different"); +} diff --git a/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u256.yml b/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u256.yml index 4fe24655c4a..27a1b10cf2e 100644 --- a/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u256.yml +++ b/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u256.yml @@ -1,42 +1,54 @@ benches: bench_icrc1_transfers: total: - instructions: 13798815361 - heap_increase: 172 - stable_memory_increase: 128 + instructions: 58832813772 + heap_increase: 271 + stable_memory_increase: 256 scopes: - before_upgrade: - instructions: 13630531777 + icrc1_transfer: + instructions: 13635001695 heap_increase: 43 stable_memory_increase: 0 - post_upgrade: - instructions: 118601062 + icrc2_approve: + instructions: 20413485760 + heap_increase: 41 + stable_memory_increase: 128 + icrc2_transfer_from: + instructions: 24042619927 + heap_increase: 5 + stable_memory_increase: 0 + icrc3_get_blocks: + instructions: 7877258 heap_increase: 0 stable_memory_increase: 0 + post_upgrade: + instructions: 354777092 + heap_increase: 53 + stable_memory_increase: 0 pre_upgrade: - instructions: 49679478 + instructions: 149556765 heap_increase: 129 stable_memory_increase: 128 upgrade: - instructions: 168282130 - heap_increase: 129 + instructions: 504335921 + heap_increase: 182 stable_memory_increase: 128 bench_upgrade_baseline: total: - instructions: 8684974 + instructions: 8684182 heap_increase: 258 stable_memory_increase: 128 scopes: post_upgrade: - instructions: 8606422 + instructions: 8605997 heap_increase: 129 stable_memory_increase: 0 pre_upgrade: - instructions: 76145 + instructions: 75778 heap_increase: 129 stable_memory_increase: 128 upgrade: - instructions: 8684285 + instructions: 8683493 heap_increase: 258 stable_memory_increase: 128 -version: 0.1.7 +version: 0.1.8 diff --git a/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u64.yml b/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u64.yml index 7e7164f34e5..fd17caa5c7c 100644 --- a/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u64.yml +++ b/rs/ledger_suite/icrc1/ledger/canbench_results/canbench_u64.yml @@ -1,42 +1,54 @@ benches: bench_icrc1_transfers: total: - instructions: 13237283790 - heap_increase: 171 - stable_memory_increase: 128 + instructions: 56837535933 + heap_increase: 271 + stable_memory_increase: 256 scopes: - before_upgrade: - instructions: 13068913917 + icrc1_transfer: + instructions: 13071791984 heap_increase: 42 stable_memory_increase: 0 - post_upgrade: - instructions: 118797275 + icrc2_approve: + instructions: 19627513485 + heap_increase: 29 + stable_memory_increase: 128 + icrc2_transfer_from: + instructions: 23404082941 + heap_increase: 18 + stable_memory_increase: 0 + icrc3_get_blocks: + instructions: 7540214 heap_increase: 0 stable_memory_increase: 0 + post_upgrade: + instructions: 353134588 + heap_increase: 53 + stable_memory_increase: 0 pre_upgrade: - instructions: 49569466 + instructions: 149315334 heap_increase: 129 stable_memory_increase: 128 upgrade: - instructions: 168368331 - heap_increase: 129 + instructions: 502451986 + heap_increase: 182 stable_memory_increase: 128 bench_upgrade_baseline: total: - instructions: 8686052 + instructions: 8683414 heap_increase: 258 stable_memory_increase: 128 scopes: post_upgrade: - instructions: 8606533 + instructions: 8604304 heap_increase: 129 stable_memory_increase: 0 pre_upgrade: - instructions: 77112 + instructions: 76703 heap_increase: 129 stable_memory_increase: 128 upgrade: - instructions: 8685363 + instructions: 8682725 heap_increase: 258 stable_memory_increase: 128 -version: 0.1.7 +version: 0.1.8 diff --git a/rs/ledger_suite/icrc1/ledger/src/benches/benches_u256.rs b/rs/ledger_suite/icrc1/ledger/src/benches/benches_u256.rs index c142d92fcc8..2291972e9bd 100644 --- a/rs/ledger_suite/icrc1/ledger/src/benches/benches_u256.rs +++ b/rs/ledger_suite/icrc1/ledger/src/benches/benches_u256.rs @@ -1,16 +1,18 @@ use crate::{ benches::{ - assert_has_num_balances, emulate_archive_blocks, icrc1_transfer, max_length_principal, - mint_tokens, upgrade, NUM_TRANSFERS, + assert_has_num_balances, emulate_archive_blocks, icrc_transfer, mint_tokens, test_account, + test_account_offset, upgrade, NUM_GET_BLOCKS, NUM_OPERATIONS, }, - init_state, Access, Account, LOG, + icrc2_approve_not_async, icrc3_get_blocks, init_state, Access, Account, LOG, }; use assert_matches::assert_matches; use canbench_rs::{bench, BenchResult}; -use candid::Principal; +use candid::{Nat, Principal}; use ic_icrc1_ledger::{FeatureFlags, InitArgs, InitArgsBuilder}; use ic_ledger_canister_core::archive::ArchiveOptions; use icrc_ledger_types::icrc1::transfer::TransferArg; +use icrc_ledger_types::icrc2::approve::ApproveArgs; +use icrc_ledger_types::icrc3::blocks::GetBlocksRequest; const MINTER_PRINCIPAL: Principal = Principal::from_slice(&[0_u8, 0, 0, 0, 2, 48, 0, 156, 1, 1]); @@ -31,22 +33,74 @@ fn bench_icrc1_transfers() -> BenchResult { canbench_rs::bench_fn(|| { { - let _p = canbench_rs::bench_scope("before_upgrade"); - for i in 0..NUM_TRANSFERS { + let _p = canbench_rs::bench_scope("icrc1_transfer"); + for i in 0..NUM_OPERATIONS { let transfer = TransferArg { from_subaccount: account_with_tokens.subaccount, - to: Account { - owner: max_length_principal(i), - subaccount: Some([11_u8; 32]), - }, + to: test_account(i), created_at_time: Some(start_time + i as u64), ..cketh_transfer() }; - let result = icrc1_transfer(account_with_tokens.owner, transfer.clone()); + let result = icrc_transfer(account_with_tokens.owner, None, transfer.clone()); assert_matches!(result, Ok(_)); emulate_archive_blocks::(&LOG); } - assert_has_num_balances(NUM_TRANSFERS + 2); + assert_has_num_balances(NUM_OPERATIONS + 2); + } + { + let _p = canbench_rs::bench_scope("icrc2_approve"); + for i in 0..NUM_OPERATIONS { + let approve = ApproveArgs { + from_subaccount: account_with_tokens.subaccount, + spender: test_account(i), + created_at_time: Some(start_time + i as u64), + amount: u128::MAX.into(), + expected_allowance: Some(0u64.into()), + expires_at: Some(u64::MAX), + fee: None, + memo: Some(MEMO.to_vec().into()), + }; + let result = icrc2_approve_not_async(account_with_tokens.owner, approve.clone()); + assert_matches!(result, Ok(_)); + emulate_archive_blocks::(&LOG); + } + } + { + let _p = canbench_rs::bench_scope("icrc2_transfer_from"); + for i in 0..NUM_OPERATIONS { + let spender = test_account(i); + let transfer = TransferArg { + from_subaccount: account_with_tokens.subaccount, + to: test_account_offset(i), + created_at_time: Some(start_time + i as u64), + ..cketh_transfer() + }; + let result = + icrc_transfer(account_with_tokens.owner, Some(spender), transfer.clone()); + assert_matches!(result, Ok(_)); + emulate_archive_blocks::(&LOG); + } + assert_has_num_balances(2 * NUM_OPERATIONS + 2); + } + for i in 0..NUM_GET_BLOCKS { + let spender = test_account(i); + let transfer = TransferArg { + from_subaccount: account_with_tokens.subaccount, + to: test_account_offset(i), + created_at_time: Some(1_000_000_000 + start_time + i as u64), + ..cketh_transfer() + }; + let result = icrc_transfer(account_with_tokens.owner, Some(spender), transfer.clone()); + assert_matches!(result, Ok(_)); + } + { + let req = GetBlocksRequest { + start: Nat::from(3 * NUM_OPERATIONS), + length: Nat::from(NUM_GET_BLOCKS), + }; + let _p = canbench_rs::bench_scope("icrc3_get_blocks"); + let blocks_res = icrc3_get_blocks(vec![req]); + assert_eq!(blocks_res.blocks.len(), NUM_GET_BLOCKS as usize); } upgrade(); }) @@ -85,6 +139,13 @@ fn cketh_ledger_init_args_with_archive() -> InitArgs { .build() } +const MEMO: [u8; 61] = [ + 0x82_u8, 0x00, 0x83, 0x54, 0x04, 0xc5, 0x63, 0x84, 0x17, 0x78, 0xc9, 0x3f, 0x41, 0xdc, 0x1a, + 0x89, 0x82, 0x1a, 0xe1, 0xc6, 0x75, 0xbb, 0xe8, 0x15, 0x58, 0x20, 0xb5, 0xa1, 0x01, 0xfb, 0x96, + 0xc5, 0xcf, 0x22, 0x4d, 0xf0, 0xd5, 0x02, 0x9b, 0x56, 0xbe, 0x81, 0xfc, 0x65, 0xce, 0x61, 0xf8, + 0x99, 0x11, 0xb7, 0x71, 0x23, 0x27, 0x8a, 0xe7, 0xf4, 0x67, 0xb7, 0x19, 0x01, 0x2c, +]; + /// ckETH ledger transaction 495542 fn cketh_transfer() -> TransferArg { TransferArg { @@ -98,16 +159,7 @@ fn cketh_transfer() -> TransferArg { }, fee: None, created_at_time: None, - memo: Some( - vec![ - 0x82_u8, 0x00, 0x83, 0x54, 0x04, 0xc5, 0x63, 0x84, 0x17, 0x78, 0xc9, 0x3f, 0x41, - 0xdc, 0x1a, 0x89, 0x82, 0x1a, 0xe1, 0xc6, 0x75, 0xbb, 0xe8, 0x15, 0x58, 0x20, 0xb5, - 0xa1, 0x01, 0xfb, 0x96, 0xc5, 0xcf, 0x22, 0x4d, 0xf0, 0xd5, 0x02, 0x9b, 0x56, 0xbe, - 0x81, 0xfc, 0x65, 0xce, 0x61, 0xf8, 0x99, 0x11, 0xb7, 0x71, 0x23, 0x27, 0x8a, 0xe7, - 0xf4, 0x67, 0xb7, 0x19, 0x01, 0x2c, - ] - .into(), - ), + memo: Some(MEMO.to_vec().into()), amount: 19_998_200_000_000_000_000_u128.into(), } } diff --git a/rs/ledger_suite/icrc1/ledger/src/benches/benches_u64.rs b/rs/ledger_suite/icrc1/ledger/src/benches/benches_u64.rs index b3fbce97763..183b545f168 100644 --- a/rs/ledger_suite/icrc1/ledger/src/benches/benches_u64.rs +++ b/rs/ledger_suite/icrc1/ledger/src/benches/benches_u64.rs @@ -1,15 +1,17 @@ use crate::benches::{ - assert_has_num_balances, emulate_archive_blocks, icrc1_transfer, max_length_principal, - mint_tokens, upgrade, NUM_TRANSFERS, + assert_has_num_balances, emulate_archive_blocks, icrc_transfer, mint_tokens, test_account, + test_account_offset, upgrade, NUM_GET_BLOCKS, NUM_OPERATIONS, }; -use crate::{init_state, Access, LOG}; +use crate::{icrc2_approve_not_async, icrc3_get_blocks, init_state, Access, LOG}; use assert_matches::assert_matches; use canbench_rs::{bench, BenchResult}; -use candid::Principal; +use candid::{Nat, Principal}; use ic_icrc1_ledger::{FeatureFlags, InitArgs, InitArgsBuilder}; use ic_ledger_canister_core::archive::ArchiveOptions; use icrc_ledger_types::icrc1::account::Account; use icrc_ledger_types::icrc1::transfer::TransferArg; +use icrc_ledger_types::icrc2::approve::ApproveArgs; +use icrc_ledger_types::icrc3::blocks::GetBlocksRequest; const MINTER_PRINCIPAL: Principal = Principal::from_slice(&[0_u8, 0, 0, 0, 2, 48, 0, 7, 1, 1]); @@ -30,22 +32,74 @@ fn bench_icrc1_transfers() -> BenchResult { canbench_rs::bench_fn(|| { { - let _p = canbench_rs::bench_scope("before_upgrade"); - for i in 0..NUM_TRANSFERS { + let _p = canbench_rs::bench_scope("icrc1_transfer"); + for i in 0..NUM_OPERATIONS { let transfer = TransferArg { from_subaccount: account_with_tokens.subaccount, - to: Account { - owner: max_length_principal(i), - subaccount: Some([11_u8; 32]), - }, + to: test_account(i), created_at_time: Some(start_time + i as u64), ..ckbtc_transfer() }; - let result = icrc1_transfer(account_with_tokens.owner, transfer.clone()); + let result = icrc_transfer(account_with_tokens.owner, None, transfer.clone()); assert_matches!(result, Ok(_)); emulate_archive_blocks::(&LOG); } - assert_has_num_balances(NUM_TRANSFERS + 2); + assert_has_num_balances(NUM_OPERATIONS + 2); + } + { + let _p = canbench_rs::bench_scope("icrc2_approve"); + for i in 0..NUM_OPERATIONS { + let approve = ApproveArgs { + from_subaccount: account_with_tokens.subaccount, + spender: test_account(i), + created_at_time: Some(start_time + i as u64), + amount: u64::MAX.into(), + expected_allowance: Some(0u64.into()), + expires_at: Some(u64::MAX), + fee: None, + memo: Some(MEMO.to_vec().into()), + }; + let result = icrc2_approve_not_async(account_with_tokens.owner, approve.clone()); + assert_matches!(result, Ok(_)); + emulate_archive_blocks::(&LOG); + } + } + { + let _p = canbench_rs::bench_scope("icrc2_transfer_from"); + for i in 0..NUM_OPERATIONS { + let spender = test_account(i); + let transfer = TransferArg { + from_subaccount: account_with_tokens.subaccount, + to: test_account_offset(i), + created_at_time: Some(start_time + i as u64), + ..ckbtc_transfer() + }; + let result = + icrc_transfer(account_with_tokens.owner, Some(spender), transfer.clone()); + assert_matches!(result, Ok(_)); + emulate_archive_blocks::(&LOG); + } + assert_has_num_balances(2 * NUM_OPERATIONS + 2); + } + for i in 0..NUM_GET_BLOCKS { + let spender = test_account(i); + let transfer = TransferArg { + from_subaccount: account_with_tokens.subaccount, + to: test_account_offset(i), + created_at_time: Some(1_000_000_000 + start_time + i as u64), + ..ckbtc_transfer() + }; + let result = icrc_transfer(account_with_tokens.owner, Some(spender), transfer.clone()); + assert_matches!(result, Ok(_)); + } + { + let req = GetBlocksRequest { + start: Nat::from(3 * NUM_OPERATIONS), + length: Nat::from(NUM_GET_BLOCKS), + }; + let _p = canbench_rs::bench_scope("icrc3_get_blocks"); + let blocks_res = icrc3_get_blocks(vec![req]); + assert_eq!(blocks_res.blocks.len(), NUM_GET_BLOCKS as usize); } upgrade(); }) @@ -84,6 +138,12 @@ fn ckbtc_ledger_init_args_with_archive() -> InitArgs { .build() } +const MEMO: [u8; 41] = [ + 0x82_u8, 0x00, 0x83, 0x58, 0x20, 0x18, 0x19, 0xcc, 0xd2, 0x28, 0xad, 0x2e, 0x83, 0xc6, 0xc8, + 0x63, 0x99, 0xa0, 0xd7, 0xd0, 0x2e, 0xe9, 0x75, 0x96, 0x95, 0x86, 0xf3, 0x47, 0x85, 0xf6, 0xaf, + 0x99, 0x00, 0x1e, 0x08, 0x8b, 0xa0, 0x02, 0x19, 0x07, 0xd0, +]; + /// ckBTC ledger transaction 1604556 fn ckbtc_transfer() -> TransferArg { TransferArg { @@ -97,14 +157,7 @@ fn ckbtc_transfer() -> TransferArg { }, fee: None, created_at_time: None, - memo: Some( - vec![ - 0x82_u8, 0x00, 0x83, 0x58, 0x20, 0x18, 0x19, 0xcc, 0xd2, 0x28, 0xad, 0x2e, 0x83, - 0xc6, 0xc8, 0x63, 0x99, 0xa0, 0xd7, 0xd0, 0x2e, 0xe9, 0x75, 0x96, 0x95, 0x86, 0xf3, - 0x47, 0x85, 0xf6, 0xaf, 0x99, 0x00, 0x1e, 0x08, 0x8b, 0xa0, 0x02, 0x19, 0x07, 0xd0, - ] - .into(), - ), + memo: Some(MEMO.to_vec().into()), amount: 167_708_u32.into(), } } diff --git a/rs/ledger_suite/icrc1/ledger/src/benches/mod.rs b/rs/ledger_suite/icrc1/ledger/src/benches/mod.rs index 68d36334239..bd27b926857 100644 --- a/rs/ledger_suite/icrc1/ledger/src/benches/mod.rs +++ b/rs/ledger_suite/icrc1/ledger/src/benches/mod.rs @@ -12,7 +12,8 @@ mod benches_u256; #[cfg(not(feature = "u256-tokens"))] mod benches_u64; -pub const NUM_TRANSFERS: u32 = 10_000; +pub const NUM_OPERATIONS: u32 = 10_000; +pub const NUM_GET_BLOCKS: u32 = 100; pub fn upgrade() { let _p = canbench_rs::bench_scope("upgrade"); @@ -20,8 +21,9 @@ pub fn upgrade() { post_upgrade(None); } -pub fn icrc1_transfer( +pub fn icrc_transfer( from: Principal, + spender: Option, arg: TransferArg, ) -> Result> { let from_account = Account { @@ -31,7 +33,7 @@ pub fn icrc1_transfer( execute_transfer_not_async( from_account, arg.to, - None, + spender, arg.fee, arg.amount, arg.memo, @@ -52,14 +54,26 @@ pub fn max_length_principal(index: u32) -> Principal { Principal::from_slice(&principal) } +pub fn test_account(i: u32) -> Account { + Account { + owner: max_length_principal(i), + subaccount: Some([11_u8; 32]), + } +} + +pub fn test_account_offset(i: u32) -> Account { + test_account(1_000_000_000 + i) +} + fn mint_tokens>(minter: Principal, amount: T) -> Account { let account_with_tokens = Account { owner: max_length_principal(u32::MAX), subaccount: Some([255_u8; 32]), }; assert_matches!( - icrc1_transfer( + icrc_transfer( minter, + None, TransferArg { from_subaccount: None, to: account_with_tokens, diff --git a/rs/ledger_suite/icrc1/ledger/src/main.rs b/rs/ledger_suite/icrc1/ledger/src/main.rs index 18643abf59e..154819b4249 100644 --- a/rs/ledger_suite/icrc1/ledger/src/main.rs +++ b/rs/ledger_suite/icrc1/ledger/src/main.rs @@ -1,8 +1,8 @@ #[cfg(feature = "canbench-rs")] mod benches; -use candid::candid_method; use candid::types::number::Nat; +use candid::{candid_method, Principal}; use ic_canister_log::{declare_log_buffer, export, log}; use ic_canisters_http_types::{HttpRequest, HttpResponse, HttpResponseBuilder}; use ic_cdk::api::stable::StableReader; @@ -810,15 +810,13 @@ fn get_data_certificate() -> DataCertificate { } } -#[update] -#[candid_method(update)] -async fn icrc2_approve(arg: ApproveArgs) -> Result { +fn icrc2_approve_not_async(caller: Principal, arg: ApproveArgs) -> Result { panic_if_not_ready(); let block_idx = Access::with_ledger_mut(|ledger| { let now = TimeStamp::from_nanos_since_unix_epoch(ic_cdk::api::time()); let from_account = Account { - owner: ic_cdk::api::caller(), + owner: caller, subaccount: arg.from_subaccount, }; if from_account.owner == arg.spender.owner { @@ -881,6 +879,14 @@ async fn icrc2_approve(arg: ApproveArgs) -> Result { Ok(block_idx) })?; + Ok(block_idx) +} + +#[update] +#[candid_method(update)] +async fn icrc2_approve(arg: ApproveArgs) -> Result { + let block_idx = icrc2_approve_not_async(ic_cdk::api::caller(), arg)?; + // NB. we need to set the certified data before the first async call to make sure that the // blockchain state agrees with the certificate while archiving is in progress. ic_cdk::api::set_certified_data(&Access::with_ledger(Ledger::root_hash)); diff --git a/rs/nervous_system/agent/src/agent_impl.rs b/rs/nervous_system/agent/src/agent_impl.rs index c70472a01af..586c7c2cbf5 100644 --- a/rs/nervous_system/agent/src/agent_impl.rs +++ b/rs/nervous_system/agent/src/agent_impl.rs @@ -25,7 +25,7 @@ impl CallCanisters for Agent { request: R, ) -> Result { let canister_id = canister_id.into(); - let request_bytes = request.payload(); + let request_bytes = request.payload().map_err(AgentCallError::CandidEncode)?; let response = if request.update() { let request = self .update(&canister_id, request.method()) diff --git a/rs/nervous_system/agent/src/lib.rs b/rs/nervous_system/agent/src/lib.rs index 2308ccd5adb..7bd9d86b2f9 100644 --- a/rs/nervous_system/agent/src/lib.rs +++ b/rs/nervous_system/agent/src/lib.rs @@ -22,7 +22,7 @@ mod sealed { pub trait Request: Send { fn method(&self) -> &'static str; fn update(&self) -> bool; - fn payload(&self) -> Vec; + fn payload(&self) -> Result, candid::Error>; type Response: CandidType + DeserializeOwned; } @@ -33,8 +33,8 @@ impl Request for R { fn update(&self) -> bool { Self::UPDATE } - fn payload(&self) -> Vec { - candid::encode_one(self).unwrap() + fn payload(&self) -> Result, candid::Error> { + candid::encode_one(self) } type Response = ::Response; diff --git a/rs/nervous_system/agent/src/null_request.rs b/rs/nervous_system/agent/src/null_request.rs index 93588d2bbe0..bb288477e8c 100644 --- a/rs/nervous_system/agent/src/null_request.rs +++ b/rs/nervous_system/agent/src/null_request.rs @@ -27,8 +27,8 @@ impl Request for NullRequest { fn update(&self) -> bool { self.update } - fn payload(&self) -> Vec { - Encode!().unwrap() + fn payload(&self) -> Result, candid::Error> { + Encode!() } type Response = T; diff --git a/rs/nervous_system/agent/src/pocketic_impl.rs b/rs/nervous_system/agent/src/pocketic_impl.rs index 44399fffdd6..d9e8b814408 100644 --- a/rs/nervous_system/agent/src/pocketic_impl.rs +++ b/rs/nervous_system/agent/src/pocketic_impl.rs @@ -27,7 +27,7 @@ impl CallCanisters for PocketIc { request: R, ) -> Result { let canister_id = canister_id.into(); - let request_bytes = request.payload(); + let request_bytes = request.payload().map_err(PocketIcCallError::CandidEncode)?; let response = if request.update() { self.update_call( canister_id, diff --git a/rs/nervous_system/tools/release-runscript/BUILD.bazel b/rs/nervous_system/tools/release-runscript/BUILD.bazel new file mode 100644 index 00000000000..dcdefb981ec --- /dev/null +++ b/rs/nervous_system/tools/release-runscript/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary") + +package(default_visibility = ["//visibility:public"]) + +# See rs/nervous_system/feature_test.md +DEPENDENCIES = [ + # Keep sorted. + "//rs/nervous_system/agent", + "//rs/nervous_system/clients", + "//rs/nns/common", + "//rs/nns/constants", + "//rs/types/base_types", + "@crate_index//:anyhow", + "@crate_index//:candid", + "@crate_index//:colored", + "@crate_index//:futures", + "@crate_index//:ic-agent", + "@crate_index//:rgb", + "@crate_index//:serde", + "@crate_index//:serde_json", + "@crate_index//:tempfile", + "@crate_index//:tokio", +] + +rust_binary( + name = "release-runscript", + srcs = [ + "src/main.rs", + ], + deps = DEPENDENCIES, +) diff --git a/rs/nervous_system/tools/release-runscript/Cargo.toml b/rs/nervous_system/tools/release-runscript/Cargo.toml new file mode 100644 index 00000000000..e603ef296ee --- /dev/null +++ b/rs/nervous_system/tools/release-runscript/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "release-runscript" +version.workspace = true +authors.workspace = true +edition.workspace = true +description.workspace = true +documentation.workspace = true + +[[bin]] +name = "release-runscript" +path = "src/main.rs" + +[dependencies] +anyhow = { workspace = true } +candid = { workspace = true } +colored = "2.0.0" +futures = { workspace = true } +ic-agent = { workspace = true } +ic-base-types = { path = "../../../types/base_types" } +ic-nervous-system-agent = { path = "../../agent" } +ic-nervous-system-clients = { path = "../../clients" } +ic-nervous-system-common-test-keys = { path = "../../common/test_keys" } +ic-nns-common = { path = "../../../nns/common" } +ic-nns-constants = { path = "../../../nns/constants" } +rgb = "0.8.37" +serde = { workspace = true } +serde_json = { workspace = true } +tempfile = { workspace = true } +tokio = { workspace = true } diff --git a/rs/nervous_system/tools/release-runscript/src/main.rs b/rs/nervous_system/tools/release-runscript/src/main.rs new file mode 100644 index 00000000000..952e4a9945d --- /dev/null +++ b/rs/nervous_system/tools/release-runscript/src/main.rs @@ -0,0 +1,210 @@ +use colored::*; +use std::io::{self, Write}; + +struct Step { + title: &'static str, + description: &'static str, +} + +fn main() { + let steps = vec![ + Step { + title: "Pick Release Candidate Commit", + description: "Run `./testnet/tools/nns-tools/cmd.sh latest_commit_with_prebuilt_artifacts`. +If you would like to pick a different commit, follow these steps: +2. Go to https://github.com/dfinity/ic/actions/workflows/ci-main.yml?query=branch%3Amaster+event%3Apush+is%3Asuccess +3. Find a recent commit with passing CI Main in the master branch +4. Record this commit (e.g., post to Slack) + +Pre-built artifacts check: +- Install aws tool if needed +- List available files: + aws s3 ls --no-sign-request s3://dfinity-download-public/ic/${COMMIT}/canisters/ +- Note: Our tools download from the analogous https://download.dfinity.systems/... URL", + }, + Step { + title: "Determine Upgrade Targets", + description: "Determine which NNS canisters and/or SNS WASMs need to be upgraded/published. +Only those with 'interesting' changes need to be released. + +Required checks: +1. Run: ./testnet/tools/nns-tools/list-new-commits.sh +2. Check Monday team sync meeting minutes at: + https://docs.google.com/document/d/1CPM1RlMz6UMSUQzqvdP7EDiLMomK4YeuEV7UnxQ9DAE/edit + +For SNS ledger suite (ledger, archive, and index canisters): +- Consult Financial Integrations team +- FI team should contact NNS team Friday morning about significant changes +- FI team should provide the 'Features' section of proposals +- This agreement is new - you may need to remind them +- This applies to ledger, archive, and index canisters", + }, + Step { + title: "Run NNS Upgrade Tests", + description: "Verify the commit you chose at the previous step has a green check on this page: https://github.com/dfinity/ic/actions/workflows/ci-main.yml?query=branch:master+event:push+is:success + +If not, you can also run the upgrade tests manually: + - Follow instructions in: testnet/tools/nns-tools/README.md#upgrade-testing-via-bazel + +2. SNS Testing Note: + - No manual testing needed for SNS + - Covered by sns_release_qualification in CI + - Example: Test at rs/nervous_system/integration_tests/tests/sns_release_qualification.rs", + }, + Step { + title: "Create Proposal Texts", + description: "Create proposal text for each canister to be upgraded. +This can be done in parallel with the previous testing step. + +Instructions: +1. Follow format in: testnet/tools/nns-tools/README.md#nnssns-canister-upgrade-proposal-process +2. Name conventions: + - NNS proposals: nns-*.md + - SNS proposals: sns-*.md +3. Organization: + - Put all proposal files in a dedicated directory + - Keep directory clean (nothing else in there) + - This will help with forum post generation later", + }, + Step { + title: "Submit Proposals", + description: "Submit the proposals on Friday + +Follow detailed instructions at: +testnet/tools/nns-tools/README.md#submit-the-proposals", + }, + Step { + title: "Create Forum Post", + description: "Create a forum post with the following specifications: + +1. Title Format: + 'NNS Updates (: )' + +2. Category: + Governance > NNS proposal discussion + Reference: https://forum.dfinity.org/t/nns-proposal-discussions/34492 + +3. Tags: + - Protocol-canister-management / Service-nervous-system-management + - nns / sns + +4. Content: + - Link to proposals in IC Dashboard + - Include all proposal texts + - Use six consecutive backticks (```````) to wrap proposal text + - Call out any 'interesting' changes, breaking changes, or required actions + +5. Generate Forum Content: + If your proposals are in a dedicated directory: + + For NNS upgrades: + ```bash + ./testnet/tools/nns-tools/cmd.sh \\ + generate_forum_post_nns_upgrades \\ + $PROPOSALS_DIR/nns-*.md \\ + | pbcopy + ``` + + For SNS WASM publishing: + ```bash + ./testnet/tools/nns-tools/cmd.sh \\ + generate_forum_post_sns_wasm_publish \\ + $PROPOSALS_DIR/sns-*.md \\ + | pbcopy + ``` + +6. Required Follow-ups: + - Reply to NNS Updates Aggregation Thread (https://forum.dfinity.org/t/nns-updates-aggregation-thread/23551) + - If SNS canister WASMs were published, update SNS Upgrades Aggregation Thread + (https://forum.dfinity.org/t/sns-upgrade-aggregation-thread/24259/2)", + }, + Step { + title: "Schedule Trusted Neurons Vote", + description: "Schedule calendar event for Trusted Neurons to vote the following Monday. + +Calendar Event Setup: +1. Duplicate a past event from: + https://calendar.google.com/calendar/u/0/r/eventedit/duplicate/MjJvMTdva2xtdGJuZDhoYjRjN2poZzNwM2ogY182NGYwZDdmZDYzYjNlMDYxZjE1Zjk2MTU1NWYzMmFiN2EyZmY3M2NjMWJmM2Q3ZTRkNGI3NGVjYjk1ZWVhM2M0QGc + +2. Use 'NNS Upgrades' calendar + +3. Timing: + - Usually scheduled at 6 pm Central European Time + - For multiple proposals, schedule separate sequential events + +4. Required Fields: + - Date and Time + - Title: Include canister name and proposal ID + - Description: Link to the proposal + +5. Actions: + - Click 'Save' to create event + - Send email invitations when prompted + - If people don't respond, ping @trusted-neurons in #eng-release channel", + }, + Step { + title: "Update Mainnet Canisters", + description: "After proposal execution, update mainnet-canisters.json: + +1. Run the sync command: + bazel run //rs/nervous_system/tools/sync-with-released-nevous-system-wasms + + Note: If you encounter problems, try adding --config=local + +2. Purpose of these changes: + - Tells bazel what versions are running in production + - Used by tests to verify upgrade compatibility + - Maintains build hermeticity + +3. Note on automation: + - There was a ticket for automating this (NNS1-2201) + - Currently marked as won't do", + }, + Step { + title: "Update Changelog", + description: "Update CHANGELOG.md file(s) for each proposal: + +1. For each proposal ID: + ```bash + PROPOSAL_IDS=... + + for PROPOSAL_ID in $PROPOSAL_IDS do + ./testnet/tools/nns-tools/add-release-to-changelog.sh \\ + $PROPOSAL_ID + done + ``` + +2. Best Practice: + - Combine this change with mainnet-canisters.json update in the same PR", + }, + ]; + + println!("{}", "\nNNS Release Runscript".bright_green().bold()); + println!("{}", "===================".bright_green()); + println!("This script will guide you through the NNS release process.\n"); + + for (index, step) in steps.iter().enumerate() { + print_step(index + 1, step); + + print!("\nPress Enter to continue to next step..."); + io::stdout().flush().unwrap(); + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + + // Clear screen for next step + print!("\x1B[2J\x1B[1;1H"); + } + + println!("{}", "\nRelease process complete!".bright_green().bold()); + println!("Please verify that all steps were completed successfully."); +} + +fn print_step(number: usize, step: &Step) { + println!( + "{} {}", + format!("Step {}:", number).bright_blue().bold(), + step.title.white().bold() + ); + println!("{}", "---".bright_blue()); + println!("{}\n", step.description); +} diff --git a/rs/nns/governance/src/governance.rs b/rs/nns/governance/src/governance.rs index c05c981f953..48a951b8349 100644 --- a/rs/nns/governance/src/governance.rs +++ b/rs/nns/governance/src/governance.rs @@ -251,10 +251,14 @@ const NODE_PROVIDER_REWARD_PERIOD_SECONDS: u64 = 2629800; const VALID_MATURITY_MODULATION_BASIS_POINTS_RANGE: RangeInclusive = -500..=500; -/// Maximum allowed number of Neurons' Fund participants that may participate in an SNS swap. -/// Given the maximum number of SNS neurons per swap participant (a.k.a. neuron basket count), -/// this constant can be used to obtain an upper bound for the number of SNS neurons created -/// for the Neurons' Fund participants. See also `MAX_SNS_NEURONS_PER_BASKET`. +/// Maximum allowed number of Neurons' Fund participants that may participate in an SNS swap. Given +/// the maximum number of SNS neurons per swap participant (a.k.a. neuron basket count), this +/// constant can be used to obtain an upper bound for the number of SNS neurons created for the +/// Neurons' Fund participants. See also `MAX_SNS_NEURONS_PER_BASKET`. In addition, this constant +/// also affects the upperbound of instructions needed to draw/refund maturity from/to the Neurons' +/// Fund, so before increasing this constant, the impact on the instructions used by +/// `CreateServiceNervousSystem` proposal execution also needs to be evaluated (currently, each +/// neuron takes ~120K instructions to draw/refund maturity, so the total is ~600M). pub const MAX_NEURONS_FUND_PARTICIPANTS: u64 = 5_000; impl NetworkEconomics { diff --git a/rs/nns/governance/src/neuron_store/benches.rs b/rs/nns/governance/src/neuron_store/benches.rs index 95e2da2699b..ca93870f5c1 100644 --- a/rs/nns/governance/src/neuron_store/benches.rs +++ b/rs/nns/governance/src/neuron_store/benches.rs @@ -404,6 +404,9 @@ fn draw_maturity_from_neurons_fund_stable() -> BenchResult { let mut rng = new_rng(); let mut neuron_store = NeuronStore::new(BTreeMap::new()); let mut neurons_fund_neurons = BTreeSet::new(); + // When extrapolating to `MAX_NEURONS_FUND_PARTICIPANTS` (5K) neurons, the current performance + // of 12M instructions (as of the time of writing) becomes 600M instructions. This is relatively + // small compared to the instruction limit of 50B (or the 40B limit for application subnets). for _ in 0..100 { let neuron = new_neuron_builder(&mut rng, NeuronLocation::Heap, NeuronSize::Typical) .with_maturity_e8s_equivalent(2_000_000_000) diff --git a/rs/p2p/artifact_manager/src/lib.rs b/rs/p2p/artifact_manager/src/lib.rs index 3fd2cd14d74..92949b68976 100644 --- a/rs/p2p/artifact_manager/src/lib.rs +++ b/rs/p2p/artifact_manager/src/lib.rs @@ -20,13 +20,11 @@ use std::{ time::Duration, }; use tokio::{ - sync::mpsc::{unbounded_channel, Sender, UnboundedReceiver, UnboundedSender}, + sync::mpsc::{Sender, UnboundedReceiver}, time::timeout, }; use tracing::instrument; -type ArtifactEventSender = UnboundedSender>; - /// Metrics for a client artifact processor. struct ArtifactProcessorMetrics { /// The processing time histogram. @@ -136,26 +134,18 @@ pub fn run_artifact_processor( time_source: Arc, metrics_registry: MetricsRegistry, client: Box>, - send_advert: Sender>, + outbound_tx: Sender>, + inbound_rx: UnboundedReceiver>, initial_artifacts: Vec, -) -> (Box, ArtifactEventSender) { - // Making this channel bounded can be problematic since we don't have true multiplexing - // of P2P messages. - // Possible scenario is - adverts+chunks arrive on the same channel, slow consensus - // will result on slow consuption of chunks. Slow consumption of chunks will in turn - // result in slower consumptions of adverts. Ideally adverts are consumed at rate - // independent of consensus. - #[allow(clippy::disallowed_methods)] - let (sender, receiver) = unbounded_channel(); +) -> Box { let shutdown = Arc::new(AtomicBool::new(false)); - // Spawn the processor thread let shutdown_cl = shutdown.clone(); let handle = ThreadBuilder::new() .name(format!("{}_Processor", Artifact::NAME)) .spawn(move || { for artifact in initial_artifacts { - let _ = send_advert.blocking_send(ArtifactTransmit::Deliver(ArtifactWithOpt { + let _ = outbound_tx.blocking_send(ArtifactTransmit::Deliver(ArtifactWithOpt { artifact, is_latency_sensitive: false, })); @@ -163,18 +153,14 @@ pub fn run_artifact_processor( process_messages( time_source, client, - send_advert, - receiver, + outbound_tx, + inbound_rx, ArtifactProcessorMetrics::new(metrics_registry, Artifact::NAME.to_string()), shutdown_cl, ); }) .unwrap(); - - ( - Box::new(ArtifactProcessorJoinGuard::new(handle, shutdown)), - sender, - ) + Box::new(ArtifactProcessorJoinGuard::new(handle, shutdown)) } // The artifact processor thread loop @@ -243,7 +229,8 @@ const ARTIFACT_MANAGER_TIMER_DURATION_MSEC: u64 = 200; pub fn create_ingress_handlers< PoolIngress: MutablePool + Send + Sync + ValidatedPoolReader + 'static, >( - send_advert: Sender>, + outbound_tx: Sender>, + inbound_rx: UnboundedReceiver>, time_source: Arc, ingress_pool: Arc>, ingress_handler: Arc< @@ -254,46 +241,41 @@ pub fn create_ingress_handlers< + Sync, >, metrics_registry: MetricsRegistry, -) -> ( - UnboundedSender>, - Box, -) { +) -> Box { let client = IngressProcessor::new(ingress_pool.clone(), ingress_handler); - let (jh, sender) = run_artifact_processor( + run_artifact_processor( time_source.clone(), metrics_registry, Box::new(client), - send_advert, + outbound_tx, + inbound_rx, vec![], - ); - (sender, jh) + ) } -/// Starts the event loop that pools consensus for updates on what needs to be replicated. +/// Starts the event loop that polls consensus for updates on what needs to be replicated. pub fn create_artifact_handler< Artifact: IdentifiableArtifact + Send + Sync + 'static, Pool: MutablePool + Send + Sync + ValidatedPoolReader + 'static, C: PoolMutationsProducer>::Mutations> + 'static, >( - send_advert: Sender>, + outbound_tx: Sender>, + inbound_rx: UnboundedReceiver>, change_set_producer: C, time_source: Arc, pool: Arc>, metrics_registry: MetricsRegistry, -) -> ( - UnboundedSender>, - Box, -) { +) -> Box { let inital_artifacts: Vec<_> = pool.read().unwrap().get_all_for_broadcast().collect(); let client = Processor::new(pool, change_set_producer); - let (jh, sender) = run_artifact_processor( + run_artifact_processor( time_source.clone(), metrics_registry, Box::new(client), - send_advert, + outbound_tx, + inbound_rx, inital_artifacts, - ); - (sender, jh) + ) } // TODO: make it private, it is used only for tests outside of this crate @@ -472,11 +454,14 @@ mod tests { let time_source = Arc::new(SysTimeSource::new()); let (send_tx, mut send_rx) = tokio::sync::mpsc::channel(100); + #[allow(clippy::disallowed_methods)] + let (_, inbound_rx) = tokio::sync::mpsc::unbounded_channel(); run_artifact_processor::( time_source, MetricsRegistry::default(), Box::new(DummyProcessor), send_tx, + inbound_rx, (0..10).map(Into::into).collect(), ); diff --git a/rs/p2p/consensus_manager/src/lib.rs b/rs/p2p/consensus_manager/src/lib.rs index bb2ee7d8bcf..3b957c05fde 100644 --- a/rs/p2p/consensus_manager/src/lib.rs +++ b/rs/p2p/consensus_manager/src/lib.rs @@ -16,7 +16,7 @@ use phantom_newtype::AmountOf; use tokio::{ runtime::Handle, sync::{ - mpsc::{Receiver, UnboundedSender}, + mpsc::{Receiver, Sender, UnboundedReceiver, UnboundedSender}, watch, }, }; @@ -28,7 +28,13 @@ mod sender; type StartConsensusManagerFn = Box, watch::Receiver) -> Vec>; -pub struct ConsensusManagerBuilder { +/// Same order of magnitude as the number of active artifacts. +const MAX_OUTBOUND_CHANNEL_SIZE: usize = 100_000; + +pub type AbortableBroadcastSender = Sender>; +pub type AbortableBroadcastReceiver = UnboundedReceiver>; + +pub struct AbortableBroadcastChannelBuilder { log: ReplicaLogger, metrics_registry: MetricsRegistry, rt_handle: Handle, @@ -36,7 +42,7 @@ pub struct ConsensusManagerBuilder { router: Option, } -impl ConsensusManagerBuilder { +impl AbortableBroadcastChannelBuilder { pub fn new(log: ReplicaLogger, rt_handle: Handle, metrics_registry: MetricsRegistry) -> Self { Self { log, @@ -47,18 +53,32 @@ impl ConsensusManagerBuilder { } } - pub fn add_client< + /// Creates a channel for the corresponding artifact. The channel is used to broadcast artifacts within the subnet. + pub fn abortable_broadcast_channel< Artifact: IdentifiableArtifact, WireArtifact: PbArtifact, F: FnOnce(Arc) -> D + 'static, D: ArtifactAssembler, >( &mut self, - outbound_artifacts_rx: Receiver>, - inbound_artifacts_tx: UnboundedSender>, (assembler, assembler_router): (F, Router), slot_limit: usize, + ) -> ( + AbortableBroadcastSender, + AbortableBroadcastReceiver, + // TODO: remove this by introducing a new channel from the http handler into the processor + UnboundedSender>, ) { + let (outbound_tx, outbound_rx) = tokio::sync::mpsc::channel(MAX_OUTBOUND_CHANNEL_SIZE); + // Making this channel bounded can be problematic since we don't have true multiplexing + // of P2P messages. + // Possible scenario is - adverts+chunks arrive on the same channel, slow consensus + // will result on slow consuption of chunks. Slow consumption of chunks will in turn + // result in slower consumptions of adverts. Ideally adverts are consumed at rate + // independent of consensus. + #[allow(clippy::disallowed_methods)] + let (inbound_tx, inbound_rx) = tokio::sync::mpsc::unbounded_channel(); + assert!(uri_prefix::() .chars() .all(char::is_alphabetic)); @@ -68,14 +88,15 @@ impl ConsensusManagerBuilder { let rt_handle = self.rt_handle.clone(); let metrics_registry = self.metrics_registry.clone(); + let inbound_tx_c = inbound_tx.clone(); let builder = move |transport: Arc, topology_watcher| { start_consensus_manager( log, &metrics_registry, rt_handle, - outbound_artifacts_rx, + outbound_rx, adverts_from_peers_rx, - inbound_artifacts_tx, + inbound_tx, assembler(transport.clone()), transport, topology_watcher, @@ -92,6 +113,7 @@ impl ConsensusManagerBuilder { ); self.clients.push(Box::new(builder)); + (outbound_tx, inbound_rx, inbound_tx_c) } pub fn router(&mut self) -> Router { diff --git a/rs/p2p/consensus_manager/src/receiver.rs b/rs/p2p/consensus_manager/src/receiver.rs index a448158b3d5..2d1a7e31ae1 100644 --- a/rs/p2p/consensus_manager/src/receiver.rs +++ b/rs/p2p/consensus_manager/src/receiver.rs @@ -652,6 +652,7 @@ mod tests { fn new() -> Self { let (_, adverts_received) = tokio::sync::mpsc::channel(100); + #[allow(clippy::disallowed_methods)] let (sender, unvalidated_artifact_receiver) = tokio::sync::mpsc::unbounded_channel(); let (_, topology_watcher) = watch::channel(SubnetTopology::default()); let artifact_assembler = diff --git a/rs/p2p/test_utils/src/lib.rs b/rs/p2p/test_utils/src/lib.rs index 7d749c41c3d..4135223ca9c 100644 --- a/rs/p2p/test_utils/src/lib.rs +++ b/rs/p2p/test_utils/src/lib.rs @@ -449,30 +449,31 @@ pub fn start_consensus_manager( processor: TestConsensus, ) -> ( Box, - ic_consensus_manager::ConsensusManagerBuilder, + ic_consensus_manager::AbortableBroadcastChannelBuilder, ) { let _enter = rt_handle.enter(); let pool = Arc::new(RwLock::new(processor)); - let (artifact_processor_jh, artifact_manager_event_rx, artifact_sender) = - start_test_processor(pool.clone(), pool.clone().read().unwrap().clone()); let bouncer_factory = Arc::new(pool.clone().read().unwrap().clone()); - let mut cm1 = ic_consensus_manager::ConsensusManagerBuilder::new( + let downloader = FetchArtifact::new( log.clone(), rt_handle.clone(), + pool.clone(), + bouncer_factory, MetricsRegistry::default(), ); - let downloader = FetchArtifact::new( - log, - rt_handle, - pool, - bouncer_factory, + + let mut cm1 = ic_consensus_manager::AbortableBroadcastChannelBuilder::new( + log.clone(), + rt_handle.clone(), MetricsRegistry::default(), ); - cm1.add_client( - artifact_manager_event_rx, - artifact_sender, - downloader, - usize::MAX, + let (outbound_tx, inbound_rx, _) = cm1.abortable_broadcast_channel(downloader, usize::MAX); + + let artifact_processor_jh = start_test_processor( + outbound_tx, + inbound_rx, + pool.clone(), + pool.clone().read().unwrap().clone(), ); (artifact_processor_jh, cm1) } diff --git a/rs/p2p/test_utils/src/turmoil.rs b/rs/p2p/test_utils/src/turmoil.rs index 3096d4453ab..c484641fb89 100644 --- a/rs/p2p/test_utils/src/turmoil.rs +++ b/rs/p2p/test_utils/src/turmoil.rs @@ -346,7 +346,7 @@ pub fn add_transport_to_sim( async move { let metrics_registry = MetricsRegistry::default(); - let mut consensus_builder = ic_consensus_manager::ConsensusManagerBuilder::new( + let mut consensus_builder = ic_consensus_manager::AbortableBroadcastChannelBuilder::new( log.clone(), tokio::runtime::Handle::current(), metrics_registry, @@ -370,25 +370,22 @@ pub fn add_transport_to_sim( }; let _artifact_processor_jh = if let Some(consensus) = consensus_manager_clone { - let (artifact_processor_jh, artifact_manager_event_rx, artifact_sender) = - start_test_processor( - consensus.clone(), - consensus.clone().read().unwrap().clone(), - ); let bouncer_factory = Arc::new(consensus.clone().read().unwrap().clone()); - let downloader = FetchArtifact::new( log.clone(), tokio::runtime::Handle::current(), - consensus, + consensus.clone(), bouncer_factory, MetricsRegistry::default(), ); - consensus_builder.add_client( - artifact_manager_event_rx, - artifact_sender, - downloader, - usize::MAX, + let (outbound_tx, inbound_tx, _) = + consensus_builder.abortable_broadcast_channel(downloader, usize::MAX); + + let artifact_processor_jh = start_test_processor( + outbound_tx, + inbound_tx, + consensus.clone(), + consensus.clone().read().unwrap().clone(), ); router = Some(router.unwrap_or_default().merge(consensus_builder.router())); @@ -442,22 +439,19 @@ pub fn waiter_fut( #[allow(clippy::type_complexity)] pub fn start_test_processor( + outbound_tx: mpsc::Sender>, + inbound_rx: mpsc::UnboundedReceiver>, pool: Arc>>, change_set_producer: TestConsensus, -) -> ( - Box, - mpsc::Receiver>, - mpsc::UnboundedSender>, -) { - let (tx, rx) = tokio::sync::mpsc::channel(1000); +) -> Box { let time_source = Arc::new(SysTimeSource::new()); let client = ic_artifact_manager::Processor::new(pool, change_set_producer); - let (jh, sender) = run_artifact_processor( + run_artifact_processor( time_source, MetricsRegistry::default(), Box::new(client), - tx, + outbound_tx, + inbound_rx, vec![], - ); - (jh, rx, sender) + ) } diff --git a/rs/replica/setup_ic_network/src/lib.rs b/rs/replica/setup_ic_network/src/lib.rs index 982cddc301c..44824366df2 100644 --- a/rs/replica/setup_ic_network/src/lib.rs +++ b/rs/replica/setup_ic_network/src/lib.rs @@ -15,7 +15,8 @@ use ic_consensus::{ consensus::{ConsensusBouncer, ConsensusImpl}, idkg, }; -use ic_consensus_manager::ConsensusManagerBuilder; +use ic_consensus_dkg::DkgBouncer; +use ic_consensus_manager::AbortableBroadcastChannelBuilder; use ic_consensus_utils::{crypto::ConsensusCrypto, pool_reader::PoolReader}; use ic_crypto_interfaces_sig_verification::IngressSigVerifier; use ic_crypto_tls_interfaces::TlsConfig; @@ -67,7 +68,6 @@ use tower_http::trace::TraceLayer; /// advertising the blocks. const HASHES_IN_BLOCKS_FEATURE_ENABLED: bool = false; -pub const MAX_ADVERT_BUFFER: usize = 100_000; /// This limit is used to protect against a malicious peer advertising many ingress messages. /// If no malicious peers are present the ingress pools are bounded by a separate limit. const SLOT_TABLE_LIMIT_INGRESS: usize = 50_000; @@ -246,11 +246,11 @@ fn start_consensus( Arc>, UnboundedSender>, Vec>, - ConsensusManagerBuilder, + AbortableBroadcastChannelBuilder, ) { let time_source = Arc::new(SysTimeSource::new()); - let mut new_p2p_consensus: ic_consensus_manager::ConsensusManagerBuilder = - ic_consensus_manager::ConsensusManagerBuilder::new( + let mut new_p2p_consensus: ic_consensus_manager::AbortableBroadcastChannelBuilder = + ic_consensus_manager::AbortableBroadcastChannelBuilder::new( log.clone(), rt_handle.clone(), metrics_registry.clone(), @@ -305,13 +305,6 @@ fn start_consensus( &PoolReader::new(&*consensus_pool.read().unwrap()), ))); - let (consensus_tx, consensus_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - let (certification_tx, certification_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - let (dkg_tx, dkg_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - let (ingress_tx, ingress_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - let (idkg_tx, idkg_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - let (http_outcalls_tx, http_outcalls_rx) = tokio::sync::mpsc::channel(MAX_ADVERT_BUFFER); - { let consensus_impl = ConsensusImpl::new( replica_config.clone(), @@ -337,53 +330,43 @@ fn start_consensus( let consensus_pool = Arc::clone(&consensus_pool); - // Create the consensus client. - let (client, jh) = create_artifact_handler( - consensus_tx, - consensus_impl, - time_source.clone(), - consensus_pool.clone(), - metrics_registry.clone(), - ); - - join_handles.push(jh); - let bouncer = Arc::new(ConsensusBouncer::new(metrics_registry, message_router)); - if HASHES_IN_BLOCKS_FEATURE_ENABLED { + let (outbound_tx, inbound_rx, _) = if HASHES_IN_BLOCKS_FEATURE_ENABLED { let assembler = ic_artifact_downloader::FetchStrippedConsensusArtifact::new( log.clone(), rt_handle.clone(), - consensus_pool, + consensus_pool.clone(), artifact_pools.ingress_pool.clone(), bouncer, metrics_registry.clone(), node_id, ); - new_p2p_consensus.add_client(consensus_rx, client, assembler, SLOT_TABLE_NO_LIMIT); + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT) } else { let assembler = ic_artifact_downloader::FetchArtifact::new( log.clone(), rt_handle.clone(), - consensus_pool, + consensus_pool.clone(), bouncer, metrics_registry.clone(), ); - new_p2p_consensus.add_client(consensus_rx, client, assembler, SLOT_TABLE_NO_LIMIT); + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT) }; - }; - let ingress_sender = { - // Create the ingress client. - let (client, jh) = create_ingress_handlers( - ingress_tx, - Arc::clone(&time_source) as Arc<_>, - Arc::clone(&artifact_pools.ingress_pool), - ingress_manager, + // Create the consensus client. + let jh = create_artifact_handler( + outbound_tx, + inbound_rx, + consensus_impl, + time_source.clone(), + consensus_pool, metrics_registry.clone(), ); join_handles.push(jh); + }; + let ingress_sender = { let bouncer = Arc::new(IngressBouncer::new(time_source.clone())); let assembler = ic_artifact_downloader::FetchArtifact::new( log.clone(), @@ -393,13 +376,19 @@ fn start_consensus( metrics_registry.clone(), ); - new_p2p_consensus.add_client( - ingress_rx, - client.clone(), - assembler, - SLOT_TABLE_LIMIT_INGRESS, + let (outbound_tx, inbound_rx, inbound_tx) = + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_LIMIT_INGRESS); + // Create the ingress client. + let jh = create_ingress_handlers( + outbound_tx, + inbound_rx, + Arc::clone(&time_source) as Arc<_>, + Arc::clone(&artifact_pools.ingress_pool), + ingress_manager, + metrics_registry.clone(), ); - client + join_handles.push(jh); + inbound_tx }; { @@ -413,32 +402,45 @@ fn start_consensus( log.clone(), max_certified_height_tx, ); + let bouncer = CertifierBouncer::new(metrics_registry, Arc::clone(&consensus_pool_cache)); + let assembler = ic_artifact_downloader::FetchArtifact::new( + log.clone(), + rt_handle.clone(), + artifact_pools.certification_pool.clone(), + Arc::new(bouncer), + metrics_registry.clone(), + ); + let (outbound_tx, inbound_rx, _) = + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT); // Create the certification client. - let (client, jh) = create_artifact_handler( - certification_tx, + let jh = create_artifact_handler( + outbound_tx, + inbound_rx, certifier, Arc::clone(&time_source) as Arc<_>, - Arc::clone(&artifact_pools.certification_pool), + artifact_pools.certification_pool, metrics_registry.clone(), ); join_handles.push(jh); + }; - let bouncer = CertifierBouncer::new(metrics_registry, Arc::clone(&consensus_pool_cache)); + { + let bouncer = Arc::new(DkgBouncer::new(metrics_registry)); let assembler = ic_artifact_downloader::FetchArtifact::new( log.clone(), rt_handle.clone(), - artifact_pools.certification_pool, - Arc::new(bouncer), + artifact_pools.dkg_pool.clone(), + bouncer, metrics_registry.clone(), ); - new_p2p_consensus.add_client(certification_rx, client, assembler, SLOT_TABLE_NO_LIMIT); - }; - { + let (outbound_tx, inbound_rx, _) = + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT); // Create the DKG client. - let (client, jh) = create_artifact_handler( - dkg_tx, + let jh = create_artifact_handler( + outbound_tx, + inbound_rx, ic_consensus_dkg::DkgImpl::new( node_id, Arc::clone(&consensus_crypto), @@ -448,22 +450,11 @@ fn start_consensus( log.clone(), ), Arc::clone(&time_source) as Arc<_>, - Arc::clone(&artifact_pools.dkg_pool), - metrics_registry.clone(), - ); - join_handles.push(jh); - - let bouncer = Arc::new(ic_consensus_dkg::DkgBouncer::new(metrics_registry)); - let assembler = ic_artifact_downloader::FetchArtifact::new( - log.clone(), - rt_handle.clone(), artifact_pools.dkg_pool, - bouncer, metrics_registry.clone(), ); - new_p2p_consensus.add_client(dkg_rx, client, assembler, SLOT_TABLE_NO_LIMIT); + join_handles.push(jh); }; - { let finalized = consensus_pool_cache.finalized_block(); let chain_key_config = @@ -478,9 +469,26 @@ fn start_consensus( finalized.payload.as_ref().is_summary(), finalized.payload.as_ref().as_idkg().is_some(), ); + let bouncer = Arc::new(idkg::IDkgBouncer::new( + metrics_registry, + subnet_id, + consensus_pool.read().unwrap().get_block_cache(), + Arc::clone(&state_reader), + )); + let assembler = ic_artifact_downloader::FetchArtifact::new( + log.clone(), + rt_handle.clone(), + artifact_pools.idkg_pool.clone(), + bouncer, + metrics_registry.clone(), + ); + + let (outbound_tx, inbound_rx, _) = + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT); - let (client, jh) = create_artifact_handler( - idkg_tx, + let jh = create_artifact_handler( + outbound_tx, + inbound_rx, idkg::IDkgImpl::new( node_id, consensus_pool.read().unwrap().get_block_cache(), @@ -491,31 +499,32 @@ fn start_consensus( malicious_flags, ), Arc::clone(&time_source) as Arc<_>, - Arc::clone(&artifact_pools.idkg_pool), + artifact_pools.idkg_pool, metrics_registry.clone(), ); - join_handles.push(jh); + }; - let bouncer = Arc::new(idkg::IDkgBouncer::new( - metrics_registry, - subnet_id, - consensus_pool.read().unwrap().get_block_cache(), + { + let bouncer = Arc::new(CanisterHttpGossipImpl::new( + Arc::clone(&consensus_pool_cache), Arc::clone(&state_reader), + log.clone(), )); let assembler = ic_artifact_downloader::FetchArtifact::new( log.clone(), rt_handle.clone(), - artifact_pools.idkg_pool, + artifact_pools.canister_http_pool.clone(), bouncer, metrics_registry.clone(), ); - new_p2p_consensus.add_client(idkg_rx, client, assembler, SLOT_TABLE_NO_LIMIT); - }; - { - let (client, jh) = create_artifact_handler( - http_outcalls_tx, + let (outbound_tx, inbound_rx, _) = + new_p2p_consensus.abortable_broadcast_channel(assembler, SLOT_TABLE_NO_LIMIT); + + let jh = create_artifact_handler( + outbound_tx, + inbound_rx, CanisterHttpPoolManagerImpl::new( Arc::clone(&state_reader), Arc::new(Mutex::new(canister_http_adapter_client)), @@ -527,24 +536,10 @@ fn start_consensus( log.clone(), ), Arc::clone(&time_source) as Arc<_>, - Arc::clone(&artifact_pools.canister_http_pool), - metrics_registry.clone(), - ); - join_handles.push(jh); - - let bouncer = Arc::new(CanisterHttpGossipImpl::new( - Arc::clone(&consensus_pool_cache), - Arc::clone(&state_reader), - log.clone(), - )); - let assembler = ic_artifact_downloader::FetchArtifact::new( - log.clone(), - rt_handle.clone(), artifact_pools.canister_http_pool, - bouncer, metrics_registry.clone(), ); - new_p2p_consensus.add_client(http_outcalls_rx, client, assembler, SLOT_TABLE_NO_LIMIT); + join_handles.push(jh); }; ( diff --git a/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs b/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs index da87417e25f..09f66dafdbe 100644 --- a/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs +++ b/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs @@ -1,90 +1,57 @@ -// This file is @generated by prost-build. +use std::collections::BTreeMap; + /// A principal with a particular set of permissions over a neuron. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronPermission { /// The principal that has the permissions. - #[prost(message, optional, tag = "1")] - pub principal: ::core::option::Option<::ic_base_types::PrincipalId>, + pub principal: Option<::ic_base_types::PrincipalId>, /// The list of permissions that this principal has. - #[prost(enumeration = "NeuronPermissionType", repeated, tag = "2")] - pub permission_type: ::prost::alloc::vec::Vec, + pub permission_type: Vec, } /// The id of a specific neuron, which equals the neuron's subaccount on the ledger canister /// (the account that holds the neuron's staked tokens). #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Eq, - std::hash::Hash, - Clone, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, Eq, std::hash::Hash, Clone, PartialEq, )] pub struct NeuronId { - #[prost(bytes = "vec", tag = "1")] #[serde(with = "serde_bytes")] - pub id: ::prost::alloc::vec::Vec, + pub id: Vec, } /// A sequence of NeuronIds, which is used to get prost to generate a type isomorphic to Option>. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronIds { - #[prost(message, repeated, tag = "1")] - pub neuron_ids: ::prost::alloc::vec::Vec, + pub neuron_ids: Vec, } /// The id of a specific proposal. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable, serde::Serialize)] -#[self_describing] -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct ProposalId { - #[prost(uint64, tag = "1")] - pub id: u64, -} #[derive( + Default, candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, + serde::Serialize, Clone, + Copy, PartialEq, - ::prost::Message, )] +pub struct ProposalId { + pub id: u64, +} +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct DisburseMaturityInProgress { /// This field is the quantity of maturity in e8s that has been decremented from a Neuron to /// be modulated and disbursed as SNS tokens. - #[prost(uint64, tag = "1")] pub amount_e8s: u64, - #[prost(uint64, tag = "2")] pub timestamp_of_disbursement_seconds: u64, - #[prost(message, optional, tag = "3")] - pub account_to_disburse_to: ::core::option::Option, - #[prost(uint64, optional, tag = "4")] - pub finalize_disbursement_timestamp_seconds: ::core::option::Option, + pub account_to_disburse_to: Option, + pub finalize_disbursement_timestamp_seconds: Option, } /// A neuron in the governance system. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[compare_default] -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Neuron { /// The unique id of this neuron. - #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, + pub id: Option, /// The principal or list of principals with a particular set of permissions over a neuron. - #[prost(message, repeated, tag = "2")] - pub permissions: ::prost::alloc::vec::Vec, + pub permissions: Vec, /// The cached record of the neuron's staked governance tokens, measured in /// fractions of 10E-8 of a governance token. /// @@ -92,7 +59,6 @@ pub struct Neuron { /// that can be set by each SNS. Neurons that are created by claiming a neuron, spawning a neuron, /// or splitting a neuron must have at least that stake (in the case of splitting both the parent neuron /// and the new neuron must have at least that stake). - #[prost(uint64, tag = "3")] pub cached_neuron_stake_e8s: u64, /// TODO NNS1-1052 - Update if this ticket is done and fees are burned / minted instead of tracked in this attribute. /// @@ -100,10 +66,8 @@ pub struct Neuron { /// due to making proposals that were subsequently rejected. /// Must be smaller than 'cached_neuron_stake_e8s'. When a neuron is /// disbursed, these governance tokens will be burned. - #[prost(uint64, tag = "4")] pub neuron_fees_e8s: u64, /// The timestamp, in seconds from the Unix epoch, when the neuron was created. - #[prost(uint64, tag = "5")] pub created_timestamp_seconds: u64, /// The timestamp, in seconds from the Unix epoch, when this neuron has entered /// the non-dissolving state. This is either the creation time or the last time at @@ -112,30 +76,25 @@ pub struct Neuron { /// This value is meaningless when the neuron is dissolving, since a /// dissolving neurons always has age zero. The canonical value of /// this field for a dissolving neuron is `u64::MAX`. - #[prost(uint64, tag = "6")] pub aging_since_timestamp_seconds: u64, /// The neuron's followees, specified as a map of proposal functions IDs to followees neuron IDs. /// The map's keys are represented by integers as Protobuf does not support enum keys in maps. - #[prost(btree_map = "uint64, message", tag = "11")] - pub followees: ::prost::alloc::collections::BTreeMap, + pub followees: BTreeMap, /// The accumulated unstaked maturity of the neuron, measured in "e8s equivalent", i.e., in equivalent of /// 10E-8 of a governance token. /// /// The unit is "equivalent" to insist that, while this quantity is on the /// same scale as the governance token, maturity is not directly convertible to /// governance tokens: conversion requires a minting event and the conversion rate is variable. - #[prost(uint64, tag = "12")] pub maturity_e8s_equivalent: u64, /// A percentage multiplier to be applied when calculating the voting power of a neuron. /// The multiplier's unit is a integer percentage in the range of 0 to 100. The /// voting_power_percentage_multiplier can only be less than 100 for a developer neuron /// that is created at SNS initialization. - #[prost(uint64, tag = "13")] pub voting_power_percentage_multiplier: u64, /// The ID of the NNS neuron whose Community Fund participation resulted in the /// creation of this SNS neuron. - #[prost(uint64, optional, tag = "14")] - pub source_nns_neuron_id: ::core::option::Option, + pub source_nns_neuron_id: Option, /// The accumulated staked maturity of the neuron, in "e8s equivalent" (see /// "maturity_e8s_equivalent"). Staked maturity becomes regular maturity once /// the neuron is dissolved. @@ -145,12 +104,10 @@ pub struct Neuron { /// and rewards. Once the neuron is dissolved, this maturity will be "moved" /// to 'maturity_e8s_equivalent' and will be able to be spawned (with maturity /// modulation). - #[prost(uint64, optional, tag = "15")] - pub staked_maturity_e8s_equivalent: ::core::option::Option, + pub staked_maturity_e8s_equivalent: Option, /// If set and true the maturity rewarded to this neuron for voting will be /// automatically staked and will contribute to the neuron's voting power. - #[prost(bool, optional, tag = "16")] - pub auto_stake_maturity: ::core::option::Option, + pub auto_stake_maturity: Option, /// The duration that this neuron is vesting. /// /// A neuron that is vesting is non-dissolving and cannot start dissolving until the vesting duration has elapsed. @@ -159,14 +116,12 @@ pub struct Neuron { /// for a particular SNS instance might be 1 year, but the devs of the project may set their vesting duration to 3 /// years and dissolve delay to 1 year in order to prove that they are making a minimum 4 year commitment to the /// project. - #[prost(uint64, optional, tag = "17")] - pub vesting_period_seconds: ::core::option::Option, + pub vesting_period_seconds: Option, /// Disburse maturity operations that are currently underway. /// The entries are sorted by `timestamp_of_disbursement_seconds`-values, /// with the oldest entries first, i.e. it holds for all i that: /// entry\[i\].timestamp_of_disbursement_seconds <= entry\[i+1\].timestamp_of_disbursement_seconds - #[prost(message, repeated, tag = "18")] - pub disburse_maturity_in_progress: ::prost::alloc::vec::Vec, + pub disburse_maturity_in_progress: Vec, /// The neuron's dissolve state, specifying whether the neuron is dissolving, /// non-dissolving, or dissolved. /// @@ -182,23 +137,14 @@ pub struct Neuron { /// `Dissolved`. All other states represent the dissolved /// state. That is, (a) `when_dissolved_timestamp_seconds` is set and in the past, /// (b) `when_dissolved_timestamp_seconds` is set to zero, (c) neither value is set. - #[prost(oneof = "neuron::DissolveState", tags = "7, 8")] - pub dissolve_state: ::core::option::Option, + pub dissolve_state: Option, } /// Nested message and enum types in `Neuron`. pub mod neuron { /// A list of a neuron's followees for a specific function. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Followees { - #[prost(message, repeated, tag = "1")] - pub followees: ::prost::alloc::vec::Vec, + pub followees: Vec, } /// The neuron's dissolve state, specifying whether the neuron is dissolving, /// non-dissolving, or dissolved. @@ -215,15 +161,7 @@ pub mod neuron { /// `Dissolved`. All other states represent the dissolved /// state. That is, (a) `when_dissolved_timestamp_seconds` is set and in the past, /// (b) `when_dissolved_timestamp_seconds` is set to zero, (c) neither value is set. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub enum DissolveState { /// When the dissolve timer is running, this stores the timestamp, /// in seconds from the Unix epoch, at which the neuron is dissolved. @@ -232,7 +170,6 @@ pub mod neuron { /// may pause dissolving, in which case `dissolve_delay_seconds` /// will get assigned to: `when_dissolved_timestamp_seconds - /// `. - #[prost(uint64, tag = "7")] WhenDissolvedTimestampSeconds(u64), /// When the dissolve timer is stopped, this stores how much time, /// in seconds, the dissolve timer will be started with if the neuron is set back to 'Dissolving'. @@ -241,7 +178,6 @@ pub mod neuron { /// dissolving, in which case `when_dissolved_timestamp_seconds` /// will get assigned to: ` + /// dissolve_delay_seconds`. - #[prost(uint64, tag = "8")] DissolveDelaySeconds(u64), } } @@ -257,77 +193,46 @@ pub mod neuron { /// /// Note that the target, validator and rendering methods can all coexist in /// the same canister or be on different canisters. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NervousSystemFunction { /// The unique id of this function. /// /// Ids 0-999 are reserved for native governance proposals and can't /// be used by generic NervousSystemFunction's. - #[prost(uint64, tag = "1")] pub id: u64, /// A short (<256 chars) description of the NervousSystemFunction. - #[prost(string, tag = "2")] - pub name: ::prost::alloc::string::String, + pub name: String, /// An optional description of what the NervousSystemFunction does. - #[prost(string, optional, tag = "3")] - pub description: ::core::option::Option<::prost::alloc::string::String>, - #[prost(oneof = "nervous_system_function::FunctionType", tags = "4, 5")] - pub function_type: ::core::option::Option, + pub description: Option, + pub function_type: Option, } /// Nested message and enum types in `NervousSystemFunction`. pub mod nervous_system_function { - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GenericNervousSystemFunction { /// The id of the target canister that will be called to execute the proposal. - #[prost(message, optional, tag = "2")] - pub target_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub target_canister_id: Option<::ic_base_types::PrincipalId>, /// The name of the method that will be called to execute the proposal. /// The signature of the method must be equivalent to the following: /// (proposal_data: ProposalData) -> Result<(), String>. - #[prost(string, optional, tag = "3")] - pub target_method_name: ::core::option::Option<::prost::alloc::string::String>, + pub target_method_name: Option, /// The id of the canister that will be called to validate the proposal before /// it is put up for a vote. - #[prost(message, optional, tag = "4")] - pub validator_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub validator_canister_id: Option<::ic_base_types::PrincipalId>, /// The name of the method that will be called to validate the proposal /// before it is put up for a vote. /// The signature of the method must be equivalent to the following: /// (proposal_data: ProposalData) -> Result - #[prost(string, optional, tag = "5")] - pub validator_method_name: ::core::option::Option<::prost::alloc::string::String>, + pub validator_method_name: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum FunctionType { /// Whether this is a native function (i.e. a Action::Motion or /// Action::UpgradeSnsControlledCanister) or one of user-defined /// NervousSystemFunctions. - #[prost(message, tag = "4")] NativeNervousSystemFunction(super::Empty), /// Whether this is a GenericNervousSystemFunction which can call /// any canister. - #[prost(message, tag = "5")] GenericNervousSystemFunction(GenericNervousSystemFunction), } } @@ -335,92 +240,53 @@ pub mod nervous_system_function { /// that is not build into the standard SNS and calls a canister outside /// the SNS for execution. /// The canister and method to call are derived from the `function_id`. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ExecuteGenericNervousSystemFunction { /// This enum value determines what canister to call and what /// function to call on that canister. /// /// 'function_id` must be in the range `\[1000--u64:MAX\]` as this /// can't be used to execute native functions. - #[prost(uint64, tag = "1")] pub function_id: u64, /// The payload of the nervous system function's payload. - #[prost(bytes = "vec", tag = "2")] #[serde(with = "serde_bytes")] - pub payload: ::prost::alloc::vec::Vec, + pub payload: Vec, } /// A proposal function that should guide the future strategy of the SNS's /// ecosystem but does not have immediate effect in the sense that a method is executed. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[self_describing] -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Motion { /// The text of the motion, which can at most be 100kib. - #[prost(string, tag = "1")] - pub motion_text: ::prost::alloc::string::String, + pub motion_text: String, } /// A proposal function that upgrades a canister that is controlled by the /// SNS governance canister. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct UpgradeSnsControlledCanister { /// The id of the canister that is upgraded. - #[prost(message, optional, tag = "1")] - pub canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub canister_id: Option<::ic_base_types::PrincipalId>, /// The new wasm module that the canister is upgraded to. - #[prost(bytes = "vec", tag = "2")] #[serde(with = "serde_bytes")] - pub new_canister_wasm: ::prost::alloc::vec::Vec, + pub new_canister_wasm: Vec, /// Arguments passed to the post-upgrade method of the new wasm module. - #[prost(bytes = "vec", optional, tag = "3")] #[serde(deserialize_with = "ic_utils::deserialize::deserialize_option_blob")] - pub canister_upgrade_arg: ::core::option::Option<::prost::alloc::vec::Vec>, + pub canister_upgrade_arg: Option>, /// Canister install_code mode. - #[prost( - enumeration = "::ic_protobuf::types::v1::CanisterInstallMode", - optional, - tag = "4" - )] - pub mode: ::core::option::Option, + pub mode: Option, } /// A proposal to transfer SNS treasury funds to (optionally a Subaccount of) the /// target principal. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct TransferSnsTreasuryFunds { - #[prost(enumeration = "transfer_sns_treasury_funds::TransferFrom", tag = "1")] pub from_treasury: i32, /// The amount to transfer, in e8s. - #[prost(uint64, tag = "2")] pub amount_e8s: u64, /// An optional memo to use for the transfer. - #[prost(uint64, optional, tag = "3")] - pub memo: ::core::option::Option, + pub memo: Option, /// The principal to transfer the funds to. - #[prost(message, optional, tag = "4")] - pub to_principal: ::core::option::Option<::ic_base_types::PrincipalId>, + pub to_principal: Option<::ic_base_types::PrincipalId>, /// An (optional) Subaccount of the principal to transfer the funds to. - #[prost(message, optional, tag = "5")] - pub to_subaccount: ::core::option::Option, + pub to_subaccount: Option, } /// Nested message and enum types in `TransferSnsTreasuryFunds`. pub mod transfer_sns_treasury_funds { @@ -429,16 +295,14 @@ pub mod transfer_sns_treasury_funds { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum TransferFrom { @@ -459,7 +323,7 @@ pub mod transfer_sns_treasury_funds { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "TRANSFER_FROM_UNSPECIFIED" => Some(Self::Unspecified), "TRANSFER_FROM_ICP_TREASURY" => Some(Self::IcpTreasury), @@ -471,212 +335,113 @@ pub mod transfer_sns_treasury_funds { } /// A proposal function that changes the ledger's parameters. /// Fields with None values will remain unchanged. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ManageLedgerParameters { - #[prost(uint64, optional, tag = "1")] - pub transfer_fee: ::core::option::Option, - #[prost(string, optional, tag = "2")] - pub token_name: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub token_symbol: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "4")] - pub token_logo: ::core::option::Option<::prost::alloc::string::String>, + pub transfer_fee: Option, + pub token_name: Option, + pub token_symbol: Option, + pub token_logo: Option, } /// A proposal to mint SNS tokens to (optionally a Subaccount of) the /// target principal. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct MintSnsTokens { /// The amount to transfer, in e8s. - #[prost(uint64, optional, tag = "1")] - pub amount_e8s: ::core::option::Option, + pub amount_e8s: Option, /// An optional memo to use for the transfer. - #[prost(uint64, optional, tag = "2")] - pub memo: ::core::option::Option, + pub memo: Option, /// The principal to transfer the funds to. - #[prost(message, optional, tag = "3")] - pub to_principal: ::core::option::Option<::ic_base_types::PrincipalId>, + pub to_principal: Option<::ic_base_types::PrincipalId>, /// An (optional) Subaccount of the principal to transfer the funds to. - #[prost(message, optional, tag = "4")] - pub to_subaccount: ::core::option::Option, + pub to_subaccount: Option, } /// A proposal function to change the values of SNS metadata. /// Fields with None values will remain unchanged. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ManageSnsMetadata { /// Base64 representation of the logo. Max length is 341334 characters, roughly 256 Kb. - #[prost(string, optional, tag = "1")] - pub logo: ::core::option::Option<::prost::alloc::string::String>, + pub logo: Option, /// Url string, must be between 10 and 256 characters. - #[prost(string, optional, tag = "2")] - pub url: ::core::option::Option<::prost::alloc::string::String>, + pub url: Option, /// Name string, must be between 4 and 255 characters. - #[prost(string, optional, tag = "3")] - pub name: ::core::option::Option<::prost::alloc::string::String>, + pub name: Option, /// Description string, must be between 10 and 10000 characters. - #[prost(string, optional, tag = "4")] - pub description: ::core::option::Option<::prost::alloc::string::String>, + pub description: Option, } /// A proposal function to upgrade the SNS to the next version. The versions are such that only /// one kind of canister will update at the same time. /// This returns an error if the canister cannot be upgraded or no upgrades are available. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct UpgradeSnsToNextVersion {} /// A proposal to register a list of dapps in the root canister. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct RegisterDappCanisters { /// The canister IDs to be registered (i.e. under the management of the SNS). /// The canisters must be already controlled by the SNS root canister before /// making this proposal. Any controllers besides the root canister will be /// removed when the proposal is executed. /// At least one canister ID is required. - #[prost(message, repeated, tag = "1")] - pub canister_ids: ::prost::alloc::vec::Vec<::ic_base_types::PrincipalId>, + pub canister_ids: Vec<::ic_base_types::PrincipalId>, } /// A proposal to remove a list of dapps from the SNS and assign them to new controllers -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct DeregisterDappCanisters { /// The canister IDs to be deregistered (i.e. removed from the management of the SNS). - #[prost(message, repeated, tag = "1")] - pub canister_ids: ::prost::alloc::vec::Vec<::ic_base_types::PrincipalId>, + pub canister_ids: Vec<::ic_base_types::PrincipalId>, /// The new controllers for the deregistered canisters. - #[prost(message, repeated, tag = "2")] - pub new_controllers: ::prost::alloc::vec::Vec<::ic_base_types::PrincipalId>, + pub new_controllers: Vec<::ic_base_types::PrincipalId>, } /// A proposal to manage the settings of one or more dapp canisters. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ManageDappCanisterSettings { /// The canister IDs of the dapp canisters to be modified. - #[prost(message, repeated, tag = "1")] - pub canister_ids: ::prost::alloc::vec::Vec<::ic_base_types::PrincipalId>, + pub canister_ids: Vec<::ic_base_types::PrincipalId>, /// Below are fields under CanisterSettings defined at /// - #[prost(uint64, optional, tag = "2")] - pub compute_allocation: ::core::option::Option, - #[prost(uint64, optional, tag = "3")] - pub memory_allocation: ::core::option::Option, - #[prost(uint64, optional, tag = "4")] - pub freezing_threshold: ::core::option::Option, - #[prost(uint64, optional, tag = "5")] - pub reserved_cycles_limit: ::core::option::Option, - #[prost(enumeration = "LogVisibility", optional, tag = "6")] - pub log_visibility: ::core::option::Option, - #[prost(uint64, optional, tag = "7")] - pub wasm_memory_limit: ::core::option::Option, - #[prost(uint64, optional, tag = "8")] - pub wasm_memory_threshold: ::core::option::Option, + pub compute_allocation: Option, + pub memory_allocation: Option, + pub freezing_threshold: Option, + pub reserved_cycles_limit: Option, + pub log_visibility: Option, + pub wasm_memory_limit: Option, + pub wasm_memory_threshold: Option, } /// Unlike `Governance.Version`, this message has optional fields and is the recommended one /// to use in APIs that can evolve. For example, the SNS Governance could eventually support /// a shorthand notation for SNS versions, enabling clients to specify SNS versions without having /// to set each individual SNS framework canister's WASM hash. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct SnsVersion { /// The hash of the Governance canister WASM. - #[prost(bytes = "vec", optional, tag = "1")] - pub governance_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub governance_wasm_hash: Option>, /// The hash of the Swap canister WASM. - #[prost(bytes = "vec", optional, tag = "2")] - pub swap_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub swap_wasm_hash: Option>, /// The hash of the Root canister WASM. - #[prost(bytes = "vec", optional, tag = "3")] - pub root_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub root_wasm_hash: Option>, /// The hash of the Index canister WASM. - #[prost(bytes = "vec", optional, tag = "4")] - pub index_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub index_wasm_hash: Option>, /// The hash of the Ledger canister WASM. - #[prost(bytes = "vec", optional, tag = "5")] - pub ledger_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub ledger_wasm_hash: Option>, /// The hash of the Ledger Archive canister WASM. - #[prost(bytes = "vec", optional, tag = "6")] - pub archive_wasm_hash: ::core::option::Option<::prost::alloc::vec::Vec>, + pub archive_wasm_hash: Option>, } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct AdvanceSnsTargetVersion { /// If not specified, the target will advance to the latest SNS version known to this SNS. - #[prost(message, optional, tag = "1")] - pub new_target: ::core::option::Option, + pub new_target: Option, } /// A proposal is the immutable input of a proposal submission. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[compare_default] -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Proposal { /// The proposal's title as a text, which can be at most 256 bytes. - #[prost(string, tag = "1")] - pub title: ::prost::alloc::string::String, + pub title: String, /// The description of the proposal which is a short text, composed /// using a maximum of 30000 bytes of characters. - #[prost(string, tag = "2")] - pub summary: ::prost::alloc::string::String, + pub summary: String, /// The web address of additional content required to evaluate the /// proposal, specified using HTTPS. The URL string must not be longer than /// 2000 bytes. - #[prost(string, tag = "3")] - pub url: ::prost::alloc::string::String, + pub url: String, /// The action that the proposal proposes to take on adoption. /// /// Each action is associated with an function id that can be used for following. @@ -686,11 +451,7 @@ pub struct Proposal { /// /// See `impl From<&Action> for u64` in src/types.rs for the implementation /// of this mapping. - #[prost( - oneof = "proposal::Action", - tags = "4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19" - )] - pub action: ::core::option::Option, + pub action: Option, } /// Nested message and enum types in `Proposal`. pub mod proposal { @@ -703,24 +464,20 @@ pub mod proposal { /// /// See `impl From<&Action> for u64` in src/types.rs for the implementation /// of this mapping. - #[derive( - candid::CandidType, candid::Deserialize, comparable::Comparable, strum_macros::EnumIter, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug)] #[allow(clippy::large_enum_variant)] - #[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq)] pub enum Action { /// The `Unspecified` action is used as a fallback when /// following. That is, if no followees are specified for a given /// action, the followees for this action are used instead. /// /// Id = 0. - #[prost(message, tag = "4")] Unspecified(super::Empty), /// A motion that should guide the future strategy of the SNS's ecosystem /// but does not have immediate effect in the sense that a method is executed. /// /// Id = 1. - #[prost(message, tag = "5")] Motion(super::Motion), /// Change the nervous system's parameters. /// Note that a change of a parameter will only affect future actions where @@ -732,98 +489,78 @@ pub mod proposal { /// neurons created before this change may have less stake. /// /// Id = 2. - #[prost(message, tag = "6")] ManageNervousSystemParameters(super::NervousSystemParameters), /// Upgrade a canister that is controlled by the SNS governance canister. /// /// Id = 3. - #[prost(message, tag = "7")] UpgradeSnsControlledCanister(super::UpgradeSnsControlledCanister), /// Add a new NervousSystemFunction, of generic type, to be executable by proposal. /// /// Id = 4. - #[prost(message, tag = "8")] AddGenericNervousSystemFunction(super::NervousSystemFunction), /// Remove a NervousSystemFunction, of generic type, from being executable by proposal. /// /// Id = 5. - #[prost(uint64, tag = "9")] RemoveGenericNervousSystemFunction(u64), /// Execute a method outside the SNS canisters. /// /// Ids \in \[1000, u64::MAX\]. - #[prost(message, tag = "10")] ExecuteGenericNervousSystemFunction(super::ExecuteGenericNervousSystemFunction), /// Execute an upgrade to next version on the blessed SNS upgrade path. /// /// Id = 7. - #[prost(message, tag = "11")] UpgradeSnsToNextVersion(super::UpgradeSnsToNextVersion), /// Modify values of SnsMetadata. /// /// Id = 8. - #[prost(message, tag = "12")] ManageSnsMetadata(super::ManageSnsMetadata), /// Transfer SNS treasury funds (ICP or SNS token) to an account. /// Id = 9. - #[prost(message, tag = "13")] TransferSnsTreasuryFunds(super::TransferSnsTreasuryFunds), /// Register one or more dapp canister(s) in the SNS root canister. /// /// Id = 10. - #[prost(message, tag = "14")] RegisterDappCanisters(super::RegisterDappCanisters), /// Deregister one or more dapp canister(s) in the SNS root canister. /// /// Id = 11. - #[prost(message, tag = "15")] DeregisterDappCanisters(super::DeregisterDappCanisters), /// Mint SNS tokens to an account. /// /// Id = 12. - #[prost(message, tag = "16")] MintSnsTokens(super::MintSnsTokens), /// Change some parameters on the ledger. /// /// Id = 13. - #[prost(message, tag = "17")] ManageLedgerParameters(super::ManageLedgerParameters), /// Change canister settings for one or more dapp canister(s). /// /// Id = 14. - #[prost(message, tag = "18")] ManageDappCanisterSettings(super::ManageDappCanisterSettings), /// Advance SNS target version. /// /// Id = 15. - #[prost(message, tag = "19")] AdvanceSnsTargetVersion(super::AdvanceSnsTargetVersion), } } -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[compare_default] -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GovernanceError { - #[prost(enumeration = "governance_error::ErrorType", tag = "1")] pub error_type: i32, - #[prost(string, tag = "2")] - pub error_message: ::prost::alloc::string::String, + pub error_message: String, } /// Nested message and enum types in `GovernanceError`. pub mod governance_error { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum ErrorType { @@ -911,7 +648,7 @@ pub mod governance_error { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "ERROR_TYPE_UNSPECIFIED" => Some(Self::Unspecified), "ERROR_TYPE_UNAVAILABLE" => Some(Self::Unavailable), @@ -942,73 +679,46 @@ pub mod governance_error { /// automatically caused by a neuron following other neurons. /// /// Once a ballot's vote is set it cannot be changed. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[self_describing] -#[derive(Clone, Copy, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct Ballot { /// The ballot's vote. - #[prost(enumeration = "Vote", tag = "1")] pub vote: i32, /// The voting power associated with the ballot. The voting power of a ballot /// associated with a neuron and a proposal is set at the proposal's creation /// time to the neuron's voting power at that time. - #[prost(uint64, tag = "2")] pub voting_power: u64, /// The time when the ballot's vote was populated with a decision (YES or NO, not /// UNDECIDED) in seconds since the UNIX epoch. This is only meaningful once a /// decision has been made and set to zero when the proposal associated with the /// ballot is created. - #[prost(uint64, tag = "3")] pub cast_timestamp_seconds: u64, } /// A tally of votes associated with a proposal. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[self_describing] -#[derive(Clone, Copy, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct Tally { /// The time when this tally was made, in seconds from the Unix epoch. - #[prost(uint64, tag = "1")] pub timestamp_seconds: u64, /// The number of yes votes, in voting power unit. - #[prost(uint64, tag = "2")] pub yes: u64, /// The number of no votes, in voting power unit. - #[prost(uint64, tag = "3")] pub no: u64, /// The total voting power unit of eligible neurons that can vote /// on the proposal that this tally is associated with (i.e., the sum /// of the voting power of yes, no, and undecided votes). /// This should always be greater than or equal to yes + no. - #[prost(uint64, tag = "4")] pub total: u64, } /// The wait-for-quiet state associated with a proposal, storing the /// data relevant to the "wait-for-quiet" implementation. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct WaitForQuietState { /// The current deadline of the proposal associated with this /// WaitForQuietState, in seconds from the Unix epoch. - #[prost(uint64, tag = "1")] pub current_deadline_timestamp_seconds: u64, } /// The ProposalData that contains everything related to a proposal: /// the proposal itself (immutable), as well as mutable data such as ballots. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ProposalData { /// The proposal's action. /// Types 0-999 are reserved for current (and future) core governance @@ -1031,61 +741,49 @@ pub struct ProposalData { /// Id 13 - ManageLedgerParameters proposals. /// Id 14 - ManageDappCanisterSettings proposals. /// Id 15 - AdvanceSnsTargetVersion proposals. - #[prost(uint64, tag = "1")] pub action: u64, /// This is stored here temporarily. It is also stored on the map /// that contains proposals. /// /// The unique id for this proposal. - #[prost(message, optional, tag = "2")] - pub id: ::core::option::Option, + pub id: Option, /// The NeuronId of the Neuron that made this proposal. - #[prost(message, optional, tag = "3")] - pub proposer: ::core::option::Option, + pub proposer: Option, /// The amount of governance tokens in e8s to be /// charged to the proposer if the proposal is rejected. - #[prost(uint64, tag = "4")] pub reject_cost_e8s: u64, /// The proposal originally submitted. - #[prost(message, optional, tag = "5")] - pub proposal: ::core::option::Option, + pub proposal: Option, /// The timestamp, in seconds from the Unix epoch, /// when this proposal was made. - #[prost(uint64, tag = "6")] pub proposal_creation_timestamp_seconds: u64, /// The ballots associated with a proposal, given as a map which /// maps the neurons' NeuronId to the neurons' ballots. This is /// only present as long as the proposal is not settled with /// respect to rewards. - #[prost(btree_map = "string, message", tag = "7")] - pub ballots: ::prost::alloc::collections::BTreeMap<::prost::alloc::string::String, Ballot>, + pub ballots: BTreeMap, /// The latest tally. The tally is computed only for open proposals when /// they are processed. Once a proposal is decided, i.e., /// ProposalDecisionStatus isn't open anymore, the tally never changes /// again. (But the ballots may still change as neurons may vote after /// the proposal has been decided.) - #[prost(message, optional, tag = "8")] - pub latest_tally: ::core::option::Option, + pub latest_tally: Option, /// The timestamp, in seconds since the Unix epoch, when this proposal /// was adopted or rejected. If not specified, the proposal is still 'open'. - #[prost(uint64, tag = "9")] pub decided_timestamp_seconds: u64, /// The timestamp, in seconds since the Unix epoch, when the (previously /// adopted) proposal has been executed. If not specified (i.e., still has /// the default value zero), the proposal has not (yet) been executed /// successfully. - #[prost(uint64, tag = "10")] pub executed_timestamp_seconds: u64, /// The timestamp, in seconds since the Unix epoch, when the (previously /// adopted) proposal has failed to be executed. If not specified (i.e., /// still has the default value zero), the proposal has not (yet) failed /// to execute. - #[prost(uint64, tag = "11")] pub failed_timestamp_seconds: u64, /// The reason why the (previously adopted) proposal has failed to execute. /// If not specified, the proposal has not (yet) failed to execute. - #[prost(message, optional, tag = "12")] - pub failure_reason: ::core::option::Option, + pub failure_reason: Option, /// OBSOLETE: Superseded by reward_event_end_timestamp_seconds. However, old /// proposals use this (old) field, not the new one, since they predate the new /// field. Therefore, to correctly detect whether a proposal has been rewarded, @@ -1099,11 +797,9 @@ pub struct ProposalData { /// no reward event taking this proposal into consideration happened yet. /// /// This field matches field round in RewardEvent. - #[prost(uint64, tag = "13")] pub reward_event_round: u64, /// The proposal's wait-for-quiet state. This needs to be saved in stable memory. - #[prost(message, optional, tag = "14")] - pub wait_for_quiet_state: ::core::option::Option, + pub wait_for_quiet_state: Option, /// The proposal's payload rendered as text, for display in text/UI frontends. /// This is set if the proposal is considered valid at time of submission. /// @@ -1113,8 +809,7 @@ pub struct ProposalData { /// Proposals with action of type GenericNervousSystemFunction provide no /// guarantee on the style of rendering as this is performed by the /// GenericNervousSystemFunction validator_canister. - #[prost(string, optional, tag = "15")] - pub payload_text_rendering: ::core::option::Option<::prost::alloc::string::String>, + pub payload_text_rendering: Option, /// Deprecated. From now on, this field will be set to true when new proposals /// are created. However, there ARE old proposals where this is set to false. /// @@ -1122,149 +817,83 @@ pub struct ProposalData { /// directly to Settled /// /// TODO(NNS1-2731): Delete this. - #[prost(bool, tag = "16")] pub is_eligible_for_rewards: bool, /// The initial voting period of the proposal, identical in meaning to the one in /// NervousSystemParameters, and duplicated here so the parameters can be changed /// without affecting existing proposals. - #[prost(uint64, tag = "17")] pub initial_voting_period_seconds: u64, /// The wait_for_quiet_deadline_increase_seconds of the proposal, identical in /// meaning to the one in NervousSystemParameters, and duplicated here so the /// parameters can be changed without affecting existing proposals. - #[prost(uint64, tag = "18")] pub wait_for_quiet_deadline_increase_seconds: u64, /// If populated, then the proposal is considered "settled" in terms of voting /// rewards. Prior to distribution of rewards, but after votes are no longer /// accepted, it is considered "ready to settle". - #[prost(uint64, optional, tag = "19")] - pub reward_event_end_timestamp_seconds: ::core::option::Option, + pub reward_event_end_timestamp_seconds: Option, /// Minimum "yes" votes needed for proposal adoption, as a fraction of the /// total voting power. Example: 300 basis points represents a requirement that /// 3% of the total voting power votes to adopt the proposal. - #[prost(message, optional, tag = "20")] - pub minimum_yes_proportion_of_total: - ::core::option::Option<::ic_nervous_system_proto::pb::v1::Percentage>, + pub minimum_yes_proportion_of_total: Option<::ic_nervous_system_proto::pb::v1::Percentage>, /// Minimum "yes" votes needed for proposal adoption, as a fraction of the /// exercised voting power. Example: 50_000 basis points represents a /// requirement that 50% of the exercised voting power votes to adopt the /// proposal. - #[prost(message, optional, tag = "21")] - pub minimum_yes_proportion_of_exercised: - ::core::option::Option<::ic_nervous_system_proto::pb::v1::Percentage>, + pub minimum_yes_proportion_of_exercised: Option<::ic_nervous_system_proto::pb::v1::Percentage>, /// In general, this holds data retrieved at proposal submission/creation time and used later /// during execution. This varies based on the action of the proposal. - #[prost(oneof = "proposal_data::ActionAuxiliary", tags = "22, 23, 24")] - pub action_auxiliary: ::core::option::Option, + pub action_auxiliary: Option, } /// Nested message and enum types in `ProposalData`. pub mod proposal_data { - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct TransferSnsTreasuryFundsActionAuxiliary { - #[prost(message, optional, tag = "1")] - pub valuation: ::core::option::Option, + pub valuation: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct MintSnsTokensActionAuxiliary { - #[prost(message, optional, tag = "1")] - pub valuation: ::core::option::Option, + pub valuation: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct AdvanceSnsTargetVersionActionAuxiliary { /// Corresponds to the Some(target_version) from an AdvanceSnsTargetVersion proposal, or /// to the last SNS version known to this SNS at the time of AdvanceSnsTargetVersion creation. - #[prost(message, optional, tag = "1")] - pub target_version: ::core::option::Option, + pub target_version: Option, } /// In general, this holds data retrieved at proposal submission/creation time and used later /// during execution. This varies based on the action of the proposal. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum ActionAuxiliary { - #[prost(message, tag = "22")] TransferSnsTreasuryFunds(TransferSnsTreasuryFundsActionAuxiliary), - #[prost(message, tag = "23")] MintSnsTokens(MintSnsTokensActionAuxiliary), - #[prost(message, tag = "24")] AdvanceSnsTargetVersion(AdvanceSnsTargetVersionActionAuxiliary), } } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Valuation { - #[prost(enumeration = "valuation::Token", optional, tag = "1")] - pub token: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub account: ::core::option::Option, - #[prost(uint64, optional, tag = "3")] - pub timestamp_seconds: ::core::option::Option, - #[prost(message, optional, tag = "4")] - pub valuation_factors: ::core::option::Option, + pub token: Option, + pub account: Option, + pub timestamp_seconds: Option, + pub valuation_factors: Option, } /// Nested message and enum types in `Valuation`. pub mod valuation { - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ValuationFactors { - #[prost(message, optional, tag = "1")] - pub tokens: ::core::option::Option<::ic_nervous_system_proto::pb::v1::Tokens>, - #[prost(message, optional, tag = "2")] - pub icps_per_token: ::core::option::Option<::ic_nervous_system_proto::pb::v1::Decimal>, - #[prost(message, optional, tag = "3")] - pub xdrs_per_icp: ::core::option::Option<::ic_nervous_system_proto::pb::v1::Decimal>, + pub tokens: Option<::ic_nervous_system_proto::pb::v1::Tokens>, + pub icps_per_token: Option<::ic_nervous_system_proto::pb::v1::Decimal>, + pub xdrs_per_icp: Option<::ic_nervous_system_proto::pb::v1::Decimal>, } #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum Token { @@ -1285,7 +914,7 @@ pub mod valuation { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "TOKEN_UNSPECIFIED" => Some(Self::Unspecified), "TOKEN_ICP" => Some(Self::Icp), @@ -1304,29 +933,19 @@ pub mod valuation { /// on the subnet). /// /// Required invariant: the canister code assumes that all system parameters are always set. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NervousSystemParameters { /// The number of e8s (10E-8 of a token) that a rejected /// proposal costs the proposer. - #[prost(uint64, optional, tag = "1")] - pub reject_cost_e8s: ::core::option::Option, + pub reject_cost_e8s: Option, /// The minimum number of e8s (10E-8 of a token) that can be staked in a neuron. /// /// To ensure that staking and disbursing of the neuron work, the chosen value /// must be larger than the transaction_fee_e8s. - #[prost(uint64, optional, tag = "2")] - pub neuron_minimum_stake_e8s: ::core::option::Option, + pub neuron_minimum_stake_e8s: Option, /// The transaction fee that must be paid for ledger transactions (except /// minting and burning governance tokens). - #[prost(uint64, optional, tag = "3")] - pub transaction_fee_e8s: ::core::option::Option, + pub transaction_fee_e8s: Option, /// The maximum number of proposals to keep, per action. When the /// total number of proposals for a given action is greater than this /// number, the oldest proposals that have reached final decision state @@ -1335,8 +954,7 @@ pub struct NervousSystemParameters { /// /// The number must be larger than zero and at most be as large as the /// defined ceiling MAX_PROPOSALS_TO_KEEP_PER_ACTION_CEILING. - #[prost(uint32, optional, tag = "4")] - pub max_proposals_to_keep_per_action: ::core::option::Option, + pub max_proposals_to_keep_per_action: Option, /// The initial voting period of a newly created proposal. /// A proposal's voting period may then be further increased during /// a proposal's lifecycle due to the wait-for-quiet algorithm. @@ -1344,8 +962,7 @@ pub struct NervousSystemParameters { /// The voting period must be between (inclusive) the defined floor /// INITIAL_VOTING_PERIOD_SECONDS_FLOOR and ceiling /// INITIAL_VOTING_PERIOD_SECONDS_CEILING. - #[prost(uint64, optional, tag = "5")] - pub initial_voting_period_seconds: ::core::option::Option, + pub initial_voting_period_seconds: Option, /// The wait for quiet algorithm extends the voting period of a proposal when /// there is a flip in the majority vote during the proposal's voting period. /// This parameter determines the maximum time period that the voting period @@ -1356,8 +973,7 @@ pub struct NervousSystemParameters { /// The maximum total voting period extension is 2 * wait_for_quiet_deadline_increase_seconds. /// For more information, see the wiki page on the wait-for-quiet algorithm: /// - #[prost(uint64, optional, tag = "18")] - pub wait_for_quiet_deadline_increase_seconds: ::core::option::Option, + pub wait_for_quiet_deadline_increase_seconds: Option, /// TODO NNS1-2169: This field currently has no effect. /// TODO NNS1-2169: Design and implement this feature. /// @@ -1367,34 +983,28 @@ pub struct NervousSystemParameters { /// If unset, neurons will have no followees by default. /// The set of followees for each function can be at most of size /// max_followees_per_function. - #[prost(message, optional, tag = "6")] - pub default_followees: ::core::option::Option, + pub default_followees: Option, /// The maximum number of allowed neurons. When this maximum is reached, no new /// neurons will be created until some are removed. /// /// This number must be larger than zero and at most as large as the defined /// ceiling MAX_NUMBER_OF_NEURONS_CEILING. - #[prost(uint64, optional, tag = "7")] - pub max_number_of_neurons: ::core::option::Option, + pub max_number_of_neurons: Option, /// The minimum dissolve delay a neuron must have to be eligible to vote. /// /// The chosen value must be smaller than max_dissolve_delay_seconds. - #[prost(uint64, optional, tag = "8")] - pub neuron_minimum_dissolve_delay_to_vote_seconds: ::core::option::Option, + pub neuron_minimum_dissolve_delay_to_vote_seconds: Option, /// The maximum number of followees each neuron can establish for each nervous system function. /// /// This number can be at most as large as the defined ceiling /// MAX_FOLLOWEES_PER_FUNCTION_CEILING. - #[prost(uint64, optional, tag = "9")] - pub max_followees_per_function: ::core::option::Option, + pub max_followees_per_function: Option, /// The maximum dissolve delay that a neuron can have. That is, the maximum /// that a neuron's dissolve delay can be increased to. The maximum is also enforced /// when saturating the dissolve delay bonus in the voting power computation. - #[prost(uint64, optional, tag = "10")] - pub max_dissolve_delay_seconds: ::core::option::Option, + pub max_dissolve_delay_seconds: Option, /// The age of a neuron that saturates the age bonus for the voting power computation. - #[prost(uint64, optional, tag = "12")] - pub max_neuron_age_for_age_bonus: ::core::option::Option, + pub max_neuron_age_for_age_bonus: Option, /// The max number of proposals for which ballots are still stored, i.e., /// unsettled proposals. If this number of proposals is reached, new proposals /// can only be added in exceptional cases (for few proposals it is defined @@ -1403,26 +1013,21 @@ pub struct NervousSystemParameters { /// /// This number must be larger than zero and at most as large as the defined /// ceiling MAX_NUMBER_OF_PROPOSALS_WITH_BALLOTS_CEILING. - #[prost(uint64, optional, tag = "14")] - pub max_number_of_proposals_with_ballots: ::core::option::Option, + pub max_number_of_proposals_with_ballots: Option, /// The default set of neuron permissions granted to the principal claiming a neuron. - #[prost(message, optional, tag = "15")] - pub neuron_claimer_permissions: ::core::option::Option, + pub neuron_claimer_permissions: Option, /// The superset of neuron permissions a principal with permission /// `NeuronPermissionType::ManagePrincipals` for a given neuron can grant to another /// principal for this same neuron. /// If this set changes via a ManageNervousSystemParameters proposal, previous /// neurons' permissions will be unchanged and only newly granted permissions will be affected. - #[prost(message, optional, tag = "16")] - pub neuron_grantable_permissions: ::core::option::Option, + pub neuron_grantable_permissions: Option, /// The maximum number of principals that can have permissions for a neuron - #[prost(uint64, optional, tag = "17")] - pub max_number_of_principals_per_neuron: ::core::option::Option, + pub max_number_of_principals_per_neuron: Option, /// When this field is not populated, voting rewards are "disabled". Once this /// is set, it probably should not be changed, because the results would /// probably be pretty confusing. - #[prost(message, optional, tag = "19")] - pub voting_rewards_parameters: ::core::option::Option, + pub voting_rewards_parameters: Option, /// E.g. if a large dissolve delay can double the voting power of a neuron, /// then this field would have a value of 100, indicating a maximum of /// 100% additional voting power. @@ -1430,14 +1035,12 @@ pub struct NervousSystemParameters { /// For no bonus, this should be set to 0. /// /// To achieve functionality equivalent to NNS, this should be set to 100. - #[prost(uint64, optional, tag = "20")] - pub max_dissolve_delay_bonus_percentage: ::core::option::Option, + pub max_dissolve_delay_bonus_percentage: Option, /// Analogous to the previous field (see the previous comment), /// but this one relates to neuron age instead of dissolve delay. /// /// To achieve functionality equivalent to NNS, this should be set to 25. - #[prost(uint64, optional, tag = "21")] - pub max_age_bonus_percentage: ::core::option::Option, + pub max_age_bonus_percentage: Option, /// By default, maturity modulation is enabled; however, an SNS can use this /// field to disable it. When disabled, this canister will still poll the /// Cycles Minting Canister (CMC), and store the value received therefrom. @@ -1446,18 +1049,9 @@ pub struct NervousSystemParameters { /// The reason we call this "disabled" instead of (positive) "enabled" is so /// that the PB default (bool fields are false) and our application default /// (enabled) agree. - #[prost(bool, optional, tag = "22")] - pub maturity_modulation_disabled: ::core::option::Option, + pub maturity_modulation_disabled: Option, } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct VotingRewardsParameters { /// The amount of time between reward events. /// @@ -1473,14 +1067,12 @@ pub struct VotingRewardsParameters { /// within a few seconds of this. /// /// This supersedes super.reward_distribution_period_seconds. - #[prost(uint64, optional, tag = "1")] - pub round_duration_seconds: ::core::option::Option, + pub round_duration_seconds: Option, /// The amount of time that the growth rate changes (presumably, decreases) /// from the initial growth rate to the final growth rate. (See the two /// *_reward_rate_basis_points fields bellow.) The transition is quadratic, and /// levels out at the end of the growth rate transition period. - #[prost(uint64, optional, tag = "3")] - pub reward_rate_transition_duration_seconds: ::core::option::Option, + pub reward_rate_transition_duration_seconds: Option, /// The amount of rewards is proportional to token_supply * current_rate. In /// turn, current_rate is somewhere between `initial_reward_rate_basis_points` /// and `final_reward_rate_basis_points`. In the first reward period, it is the @@ -1490,37 +1082,19 @@ pub struct VotingRewardsParameters { /// quadratic, and levels out at the end of the growth rate transition period. /// /// (A basis point is one in ten thousand.) - #[prost(uint64, optional, tag = "4")] - pub initial_reward_rate_basis_points: ::core::option::Option, - #[prost(uint64, optional, tag = "5")] - pub final_reward_rate_basis_points: ::core::option::Option, + pub initial_reward_rate_basis_points: Option, + pub final_reward_rate_basis_points: Option, } /// The set of default followees that every newly created neuron will follow per function. /// This is specified as a mapping of proposal functions to followees for that function. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct DefaultFollowees { - #[prost(btree_map = "uint64, message", tag = "1")] - pub followees: ::prost::alloc::collections::BTreeMap, + pub followees: BTreeMap, } /// A wrapper for a list of neuron permissions. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronPermissionList { - #[prost(enumeration = "NeuronPermissionType", repeated, tag = "1")] - pub permissions: ::prost::alloc::vec::Vec, + pub permissions: Vec, } /// A record of when voting rewards were determined, and neuron maturity /// increased for participation in voting on proposals. @@ -1531,14 +1105,7 @@ pub struct NeuronPermissionList { /// To make it a little easier to eventually deduplicate NNS and SNS governance /// code, tags should be chosen so that it is new to BOTH this and the NNS /// RewardEvent. (This also applies to other message definitions.) -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct RewardEvent { /// DEPRECATED: Use end_timestamp_seconds instead. /// @@ -1554,23 +1121,19 @@ pub struct RewardEvent { /// it was not possible to process a reward event for a while. This means that /// successive values in this field might not be consecutive, but they usually /// are. - #[prost(uint64, tag = "1")] pub round: u64, /// Not to be confused with round_end_timestampe_seconds. This is just used to /// record when the calculation (of voting rewards) was performed, not the time /// range/events (i.e. proposals) that was operated on. - #[prost(uint64, tag = "2")] pub actual_timestamp_seconds: u64, /// The list of proposals that were taken into account during /// this reward event. - #[prost(message, repeated, tag = "3")] - pub settled_proposals: ::prost::alloc::vec::Vec, + pub settled_proposals: Vec, /// The total amount of reward that was distributed during this reward event. /// /// The unit is "e8s equivalent" to insist that, while this quantity is on /// the same scale as governance tokens, maturity is not directly convertible /// to governance tokens: conversion requires a minting event. - #[prost(uint64, tag = "4")] pub distributed_e8s_equivalent: u64, /// All proposals that were "ready to settle" up to this time were /// considered. @@ -1587,8 +1150,7 @@ pub struct RewardEvent { /// Being able to change round duration does not exist in NNS (yet), and there /// is (currently) no intention to add that feature, but it could be done by /// making similar changes. - #[prost(uint64, optional, tag = "5")] - pub end_timestamp_seconds: ::core::option::Option, + pub end_timestamp_seconds: Option, /// In some cases, the rewards that would have been distributed in one round are /// "rolled over" into the next reward event. This field keeps track of how many /// rounds have passed since the last time rewards were distributed (rather @@ -1607,8 +1169,7 @@ pub struct RewardEvent { /// settled to distribute rewards for. /// /// In both of these cases, the rewards purse rolls over into the next round. - #[prost(uint64, optional, tag = "6")] - pub rounds_since_last_distribution: ::core::option::Option, + pub rounds_since_last_distribution: Option, /// The total amount of rewards that was available during the reward event. /// /// The e8s_equivalent_to_be_rolled_over method returns this when @@ -1619,32 +1180,25 @@ pub struct RewardEvent { /// Warning: There is a field with the same name in NNS, but different tags are /// used. Also, this uses the `optional` keyword (whereas, the NNS analog does /// not). - #[prost(uint64, optional, tag = "8")] - pub total_available_e8s_equivalent: ::core::option::Option, + pub total_available_e8s_equivalent: Option, } /// The representation of the whole governance system, containing all /// information about the governance system that must be kept /// across upgrades of the governance system, i.e. kept in stable memory. -#[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] -#[compare_default] -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Governance { /// The current set of neurons registered in governance as a map from /// neuron IDs to neurons. - #[prost(btree_map = "string, message", tag = "1")] - pub neurons: ::prost::alloc::collections::BTreeMap<::prost::alloc::string::String, Neuron>, + pub neurons: BTreeMap, /// The current set of proposals registered in governance as a map /// from proposal IDs to the proposals' data. - #[prost(btree_map = "uint64, message", tag = "2")] - pub proposals: ::prost::alloc::collections::BTreeMap, + pub proposals: BTreeMap, /// The nervous system parameters that define and can be set by /// each nervous system. - #[prost(message, optional, tag = "8")] - pub parameters: ::core::option::Option, + pub parameters: Option, /// TODO IC-1168: update when rewards are introduced /// The latest reward event. - #[prost(message, optional, tag = "9")] - pub latest_reward_event: ::core::option::Option, + pub latest_reward_event: Option, /// The in-flight neuron ledger commands as a map from neuron IDs /// to commands. /// @@ -1666,87 +1220,54 @@ pub struct Governance { /// Because we know exactly what was going on, we should have the /// information necessary to reconcile the state, using custom code /// added on upgrade, if necessary. - #[prost(btree_map = "string, message", tag = "10")] - pub in_flight_commands: ::prost::alloc::collections::BTreeMap< - ::prost::alloc::string::String, - governance::NeuronInFlightCommand, - >, + pub in_flight_commands: BTreeMap, /// The timestamp that is considered genesis for the governance /// system, in seconds since the Unix epoch. That is, the time /// at which `canister_init` was run for the governance canister. - #[prost(uint64, tag = "11")] pub genesis_timestamp_seconds: u64, - #[prost(message, optional, tag = "13")] - pub metrics: ::core::option::Option, + pub metrics: Option, /// The canister ID of the ledger canister. - #[prost(message, optional, tag = "16")] - pub ledger_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub ledger_canister_id: Option<::ic_base_types::PrincipalId>, /// The canister ID of the root canister. - #[prost(message, optional, tag = "17")] - pub root_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub root_canister_id: Option<::ic_base_types::PrincipalId>, /// ID to NervousSystemFunction (which has an id field). - #[prost(btree_map = "uint64, message", tag = "18")] - pub id_to_nervous_system_functions: - ::prost::alloc::collections::BTreeMap, - #[prost(enumeration = "governance::Mode", tag = "19")] + pub id_to_nervous_system_functions: BTreeMap, pub mode: i32, /// The canister ID of the swap canister. /// /// When this is unpopulated, mode should be Normal, and when this is /// populated, mode should be PreInitializationSwap. - #[prost(message, optional, tag = "20")] - pub swap_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>, - #[prost(message, optional, tag = "21")] - pub sns_metadata: ::core::option::Option, + pub swap_canister_id: Option<::ic_base_types::PrincipalId>, + pub sns_metadata: Option, /// The initialization parameters used to spawn an SNS - #[prost(string, tag = "22")] - pub sns_initialization_parameters: ::prost::alloc::string::String, + pub sns_initialization_parameters: String, /// Current version that this SNS is running. - #[prost(message, optional, tag = "23")] - pub deployed_version: ::core::option::Option, + pub deployed_version: Option, /// Version SNS is in process of upgrading to. - #[prost(message, optional, tag = "24")] - pub pending_version: ::core::option::Option, - #[prost(message, optional, tag = "30")] - pub target_version: ::core::option::Option, + pub pending_version: Option, + pub target_version: Option, /// True if the run_periodic_tasks function is currently finalizing disburse maturity, meaning /// that it should finish before being called again. - #[prost(bool, optional, tag = "25")] - pub is_finalizing_disburse_maturity: ::core::option::Option, - #[prost(message, optional, tag = "26")] - pub maturity_modulation: ::core::option::Option, - #[prost(message, optional, tag = "29")] - pub cached_upgrade_steps: ::core::option::Option, + pub is_finalizing_disburse_maturity: Option, + pub maturity_modulation: Option, + pub cached_upgrade_steps: Option, /// Information about the timers that perform periodic tasks of this Governance canister. - #[prost(message, optional, tag = "31")] - pub timers: ::core::option::Option<::ic_nervous_system_proto::pb::v1::Timers>, - #[prost(message, optional, tag = "32")] - pub upgrade_journal: ::core::option::Option, + pub timers: Option<::ic_nervous_system_proto::pb::v1::Timers>, + pub upgrade_journal: Option, } /// Nested message and enum types in `Governance`. pub mod governance { + use super::*; use crate::format_full_hash; use serde::ser::SerializeStruct; /// The commands that require a neuron lock. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronInFlightCommand { /// The timestamp at which the command was issued, for debugging /// purposes. - #[prost(uint64, tag = "1")] pub timestamp: u64, - #[prost( - oneof = "neuron_in_flight_command::Command", - tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 20" - )] - pub command: ::core::option::Option, + pub command: Option, } /// Nested message and enum types in `NeuronInFlightCommand`. pub mod neuron_in_flight_command { @@ -1758,67 +1279,36 @@ pub mod governance { /// no value in actually storing the command itself, and this placeholder /// can generally be used in all sync cases. #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq, )] pub struct SyncCommand {} - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum Command { - #[prost(message, tag = "2")] Disburse(super::super::manage_neuron::Disburse), - #[prost(message, tag = "3")] Split(super::super::manage_neuron::Split), - #[prost(message, tag = "4")] MergeMaturity(super::super::manage_neuron::MergeMaturity), - #[prost(message, tag = "5")] DisburseMaturity(super::super::manage_neuron::DisburseMaturity), - #[prost(message, tag = "6")] ClaimOrRefreshNeuron(super::super::manage_neuron::ClaimOrRefresh), - #[prost(message, tag = "7")] AddNeuronPermissions(super::super::manage_neuron::AddNeuronPermissions), - #[prost(message, tag = "8")] RemoveNeuronPermissions(super::super::manage_neuron::RemoveNeuronPermissions), - #[prost(message, tag = "9")] Configure(super::super::manage_neuron::Configure), - #[prost(message, tag = "10")] Follow(super::super::manage_neuron::Follow), - #[prost(message, tag = "11")] MakeProposal(super::super::Proposal), - #[prost(message, tag = "12")] RegisterVote(super::super::manage_neuron::RegisterVote), - #[prost(message, tag = "13")] FinalizeDisburseMaturity(super::super::manage_neuron::FinalizeDisburseMaturity), - #[prost(message, tag = "20")] SyncCommand(SyncCommand), } } /// Metrics that are too costly to compute each time when they are /// requested. - #[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] - #[compare_default] - #[derive(Clone, PartialEq, ::prost::Message)] + #[derive(candid::CandidType, candid::Deserialize, Debug, Default, Clone, PartialEq)] pub struct GovernanceCachedMetrics { /// The timestamp when these metrics were computed, as seconds since /// Unix epoch. - #[prost(uint64, tag = "1")] pub timestamp_seconds: u64, /// The total supply of governance tokens in the ledger canister. - #[prost(uint64, tag = "2")] pub total_supply_governance_tokens: u64, /// The number of dissolving neurons (i.e., in NeuronState::Dissolving). - #[prost(uint64, tag = "3")] pub dissolving_neurons_count: u64, /// The number of staked governance tokens in dissolving neurons /// (i.e., in NeuronState::Dissolving) grouped by the neurons' dissolve delay @@ -1826,16 +1316,13 @@ pub mod governance { /// This is given as a map from dissolve delays (rounded to years) /// to the sum of staked tokens in the dissolving neurons that have this /// dissolve delay. - #[prost(btree_map = "uint64, double", tag = "4")] - pub dissolving_neurons_e8s_buckets: ::prost::alloc::collections::BTreeMap, + pub dissolving_neurons_e8s_buckets: BTreeMap, /// The number of dissolving neurons (i.e., in NeuronState::Dissolving) /// grouped by their dissolve delay rounded to years. /// This is given as a map from dissolve delays (rounded to years) to /// the number of dissolving neurons that have this dissolve delay. - #[prost(btree_map = "uint64, uint64", tag = "5")] - pub dissolving_neurons_count_buckets: ::prost::alloc::collections::BTreeMap, + pub dissolving_neurons_count_buckets: BTreeMap, /// The number of non-dissolving neurons (i.e., in NeuronState::NotDissolving). - #[prost(uint64, tag = "6")] pub not_dissolving_neurons_count: u64, /// The number of staked governance tokens in non-dissolving neurons /// (i.e., in NeuronState::NotDissolving) grouped by the neurons' dissolve delay @@ -1843,65 +1330,45 @@ pub mod governance { /// This is given as a map from dissolve delays (rounded to years) /// to the sum of staked tokens in the non-dissolving neurons that have this /// dissolve delay. - #[prost(btree_map = "uint64, double", tag = "7")] - pub not_dissolving_neurons_e8s_buckets: ::prost::alloc::collections::BTreeMap, + pub not_dissolving_neurons_e8s_buckets: BTreeMap, /// The number of non-dissolving neurons (i.e., in NeuronState::NotDissolving) /// grouped by their dissolve delay rounded to years. /// This is given as a map from dissolve delays (rounded to years) to /// the number of non-dissolving neurons that have this dissolve delay. - #[prost(btree_map = "uint64, uint64", tag = "8")] - pub not_dissolving_neurons_count_buckets: ::prost::alloc::collections::BTreeMap, + pub not_dissolving_neurons_count_buckets: BTreeMap, /// The number of dissolved neurons (i.e., in NeuronState::Dissolved). - #[prost(uint64, tag = "9")] pub dissolved_neurons_count: u64, /// The number of staked governance tokens in dissolved neurons /// (i.e., in NeuronState::Dissolved). - #[prost(uint64, tag = "10")] pub dissolved_neurons_e8s: u64, /// The number of neurons that are garbage collectable, i.e., that /// have a cached stake smaller than the ledger transaction fee. - #[prost(uint64, tag = "11")] pub garbage_collectable_neurons_count: u64, /// The number of neurons that have an invalid stake, i.e., that /// have a cached stake that is larger than zero but smaller than the /// minimum neuron stake defined in the nervous system parameters. - #[prost(uint64, tag = "12")] pub neurons_with_invalid_stake_count: u64, /// The total amount of governance tokens that are staked in neurons, /// measured in fractions of 10E-8 of a governance token. - #[prost(uint64, tag = "13")] pub total_staked_e8s: u64, /// TODO: rather than taking six months, it would be more interesting to take the respective SNS's eligibility boarder here. /// The number of neurons with a dissolve delay of less than six months. - #[prost(uint64, tag = "14")] pub neurons_with_less_than_6_months_dissolve_delay_count: u64, /// The number of governance tokens in neurons with a dissolve delay of /// less than six months. - #[prost(uint64, tag = "15")] pub neurons_with_less_than_6_months_dissolve_delay_e8s: u64, } /// Metadata about this SNS. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct SnsMetadata { /// The logo for the SNS project represented as a base64 encoded string. - #[prost(string, optional, tag = "1")] - pub logo: ::core::option::Option<::prost::alloc::string::String>, + pub logo: Option, /// Url to the dapp controlled by the SNS project. - #[prost(string, optional, tag = "2")] - pub url: ::core::option::Option<::prost::alloc::string::String>, + pub url: Option, /// Name of the SNS project. This may differ from the name of the associated token. - #[prost(string, optional, tag = "3")] - pub name: ::core::option::Option<::prost::alloc::string::String>, + pub name: Option, /// Description of the SNS project. - #[prost(string, optional, tag = "4")] - pub description: ::core::option::Option<::prost::alloc::string::String>, + pub description: Option, } impl serde::Serialize for Version { @@ -1931,87 +1398,48 @@ pub mod governance { /// A version of the SNS defined by the WASM hashes of its canisters. #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Eq, - std::hash::Hash, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, Eq, std::hash::Hash, Clone, PartialEq, )] pub struct Version { /// The hash of the Root canister WASM. - #[prost(bytes = "vec", tag = "1")] #[serde(with = "serde_bytes")] - pub root_wasm_hash: ::prost::alloc::vec::Vec, + pub root_wasm_hash: Vec, /// The hash of the Governance canister WASM. - #[prost(bytes = "vec", tag = "2")] #[serde(with = "serde_bytes")] - pub governance_wasm_hash: ::prost::alloc::vec::Vec, + pub governance_wasm_hash: Vec, /// The hash of the Ledger canister WASM. - #[prost(bytes = "vec", tag = "3")] #[serde(with = "serde_bytes")] - pub ledger_wasm_hash: ::prost::alloc::vec::Vec, + pub ledger_wasm_hash: Vec, /// The hash of the Swap canister WASM. - #[prost(bytes = "vec", tag = "4")] #[serde(with = "serde_bytes")] - pub swap_wasm_hash: ::prost::alloc::vec::Vec, + pub swap_wasm_hash: Vec, /// The hash of the Ledger Archive canister WASM. - #[prost(bytes = "vec", tag = "5")] #[serde(with = "serde_bytes")] - pub archive_wasm_hash: ::prost::alloc::vec::Vec, + pub archive_wasm_hash: Vec, /// The hash of the Index canister WASM. - #[prost(bytes = "vec", tag = "6")] #[serde(with = "serde_bytes")] - pub index_wasm_hash: ::prost::alloc::vec::Vec, + pub index_wasm_hash: Vec, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct Versions { - #[prost(message, repeated, tag = "1")] - pub versions: ::prost::alloc::vec::Vec, + pub versions: Vec, } /// An upgrade in progress, defined as a version target and a time at which it is considered failed. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct PendingVersion { /// Version to be upgraded to - #[prost(message, optional, tag = "1")] - pub target_version: ::core::option::Option, + pub target_version: Option, /// Seconds since UNIX epoch to mark this as a failed version if not in sync with current version - #[prost(uint64, tag = "2")] pub mark_failed_at_seconds: u64, /// Lock to avoid checking over and over again. Also, it is a counter for how many times we have attempted to check, /// allowing us to fail in case we otherwise have gotten stuck. - #[prost(uint64, tag = "3")] pub checking_upgrade_lock: u64, /// The proposal that initiated this upgrade - #[prost(uint64, optional, tag = "4")] - pub proposal_id: ::core::option::Option, + pub proposal_id: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct MaturityModulation { /// When X maturity is disbursed, the amount that goes to the destination /// account is X * (1 + y) where y = current_basis_points / 10_000. @@ -2020,52 +1448,37 @@ pub mod governance { /// /// There is a positive relationship between the price of ICP (in XDR) and /// this value. - #[prost(int32, optional, tag = "1")] - pub current_basis_points: ::core::option::Option, + pub current_basis_points: Option, /// When current_basis_points was last updated (seconds since UNIX epoch). - #[prost(uint64, optional, tag = "2")] - pub updated_at_timestamp_seconds: ::core::option::Option, + pub updated_at_timestamp_seconds: Option, } /// The sns's local cache of the upgrade steps recieved from SNS-W. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct CachedUpgradeSteps { /// The upgrade steps that have been returned from SNS-W the last time we /// called list_upgrade_steps. - #[prost(message, optional, tag = "1")] - pub upgrade_steps: ::core::option::Option, + pub upgrade_steps: Option, /// The timestamp of the request we sent to list_upgrade_steps. /// It's possible that this is greater than the response_timestamp_seconds, because /// we update it as soon as we send the request, and only update the /// response_timestamp and the upgrade_steps when we receive the response. /// The primary use of this is that we can avoid calling list_upgrade_steps /// more frequently than necessary. - #[prost(uint64, optional, tag = "2")] - pub requested_timestamp_seconds: ::core::option::Option, + pub requested_timestamp_seconds: Option, /// The timestamp of the response we received from list_upgrade_steps (stored in upgrade_steps). - #[prost(uint64, optional, tag = "3")] - pub response_timestamp_seconds: ::core::option::Option, + pub response_timestamp_seconds: Option, } #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, - strum_macros::EnumIter, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum Mode { @@ -2090,7 +1503,7 @@ pub mod governance { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "MODE_UNSPECIFIED" => Some(Self::Unspecified), "MODE_NORMAL" => Some(Self::Normal), @@ -2101,114 +1514,50 @@ pub mod governance { } } /// Request message for 'get_metadata'. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetMetadataRequest {} /// Response message for 'get_metadata'. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetMetadataResponse { - #[prost(string, optional, tag = "1")] - pub logo: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "2")] - pub url: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub name: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "4")] - pub description: ::core::option::Option<::prost::alloc::string::String>, + pub logo: Option, + pub url: Option, + pub name: Option, + pub description: Option, } /// Request message for 'get_sns_initialization_parameters' -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetSnsInitializationParametersRequest {} /// Response message for 'get_sns_initialization_parameters' -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetSnsInitializationParametersResponse { - #[prost(string, tag = "1")] - pub sns_initialization_parameters: ::prost::alloc::string::String, + pub sns_initialization_parameters: String, } /// Request for the SNS's currently running version. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetRunningSnsVersionRequest {} /// Response with the SNS's currently running version and any upgrades /// that are in progress. /// GetUpgradeJournal is a superior API to this one that should -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetRunningSnsVersionResponse { /// The currently deployed version of the SNS. - #[prost(message, optional, tag = "1")] - pub deployed_version: ::core::option::Option, + pub deployed_version: Option, /// The upgrade in progress, if any. - #[prost(message, optional, tag = "2")] - pub pending_version: - ::core::option::Option, + pub pending_version: Option, } /// Nested message and enum types in `GetRunningSnsVersionResponse`. pub mod get_running_sns_version_response { /// The same as PendingVersion (stored in the governance proto). They are separated to make it easy to change one without changing the other. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct UpgradeInProgress { /// Version to be upgraded to - #[prost(message, optional, tag = "1")] - pub target_version: ::core::option::Option, + pub target_version: Option, /// Seconds since UNIX epoch to mark this as a failed version if not in sync with current version - #[prost(uint64, tag = "2")] pub mark_failed_at_seconds: u64, /// Lock to avoid checking over and over again. Also, it is a counter for how many times we have attempted to check, /// allowing us to fail in case we otherwise have gotten stuck. - #[prost(uint64, tag = "3")] pub checking_upgrade_lock: u64, /// The proposal that initiated this upgrade - #[prost(uint64, tag = "4")] pub proposal_id: u64, } } @@ -2216,174 +1565,74 @@ pub mod get_running_sns_version_response { /// Failed if it is past the time when it should have been marked as failed. /// This is useful in the case where the asynchronous process may have failed to /// complete -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct FailStuckUpgradeInProgressRequest {} /// Response to FailStuckUpgradeInProgressRequest -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct FailStuckUpgradeInProgressResponse {} /// Empty message to use in oneof fields that represent empty /// enums. #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - Copy, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, Copy, PartialEq, )] pub struct Empty {} /// An operation that modifies a neuron. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ManageNeuron { /// The modified neuron's subaccount which also serves as the neuron's ID. - #[prost(bytes = "vec", tag = "1")] #[serde(with = "serde_bytes")] - pub subaccount: ::prost::alloc::vec::Vec, - #[prost( - oneof = "manage_neuron::Command", - tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13" - )] - pub command: ::core::option::Option, + pub subaccount: Vec, + pub command: Option, } /// Nested message and enum types in `ManageNeuron`. pub mod manage_neuron { /// The operation that increases a neuron's dissolve delay. It can be /// increased up to a maximum defined in the nervous system parameters. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct IncreaseDissolveDelay { /// The additional dissolve delay that should be added to the neuron's /// current dissolve delay. - #[prost(uint32, tag = "1")] pub additional_dissolve_delay_seconds: u32, } /// The operation that starts dissolving a neuron, i.e., changes a neuron's /// state such that it is dissolving. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct StartDissolving {} /// The operation that stops dissolving a neuron, i.e., changes a neuron's /// state such that it is non-dissolving. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct StopDissolving {} /// An (idempotent) alternative to IncreaseDissolveDelay where the dissolve delay /// is passed as an absolute timestamp in seconds since the Unix epoch. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct SetDissolveTimestamp { /// The time when the neuron (newly) should become dissolved, in seconds /// since the Unix epoch. - #[prost(uint64, tag = "1")] pub dissolve_timestamp_seconds: u64, } /// Changes auto-stake maturity for this Neuron. While on, auto-stake /// maturity will cause all the maturity generated by voting rewards /// to this neuron to be automatically staked and contribute to the /// voting power of the neuron. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct ChangeAutoStakeMaturity { - #[prost(bool, tag = "1")] pub requested_setting_for_auto_stake_maturity: bool, } /// Commands that only configure a given neuron, but do not interact /// with the outside world. They all require the caller to have /// `NeuronPermissionType::ConfigureDissolveState` for the neuron. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct Configure { - #[prost(oneof = "configure::Operation", tags = "1, 2, 3, 4, 5")] - pub operation: ::core::option::Option, + pub operation: Option, } /// Nested message and enum types in `Configure`. pub mod configure { - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub enum Operation { - #[prost(message, tag = "1")] IncreaseDissolveDelay(super::IncreaseDissolveDelay), - #[prost(message, tag = "2")] StartDissolving(super::StartDissolving), - #[prost(message, tag = "3")] StopDissolving(super::StopDissolving), - #[prost(message, tag = "4")] SetDissolveTimestamp(super::SetDissolveTimestamp), - #[prost(message, tag = "5")] ChangeAutoStakeMaturity(super::ChangeAutoStakeMaturity), } } @@ -2392,36 +1641,20 @@ pub mod manage_neuron { /// Thereby, the neuron's accumulated fees are burned and (if relevant in /// the given nervous system) the token equivalent of the neuron's accumulated /// maturity are minted and also transferred to the specified account. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Disburse { /// The (optional) amount to disburse out of the neuron. If not specified the cached /// stake is used. - #[prost(message, optional, tag = "1")] - pub amount: ::core::option::Option, + pub amount: Option, /// The ledger account to which the disbursed tokens are transferred. - #[prost(message, optional, tag = "2")] - pub to_account: ::core::option::Option, + pub to_account: Option, } /// Nested message and enum types in `Disburse`. pub mod disburse { #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq, )] pub struct Amount { - #[prost(uint64, tag = "1")] pub e8s: u64, } } @@ -2434,97 +1667,51 @@ pub mod manage_neuron { /// the dissolve state. The parent neuron's fees and maturity (if applicable in the given /// nervous system) remain in the parent neuron and the child neuron's fees and maturity /// are initialized to be zero. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct Split { /// The amount of governance tokens (in measured in fractions of 10E-8 of /// a governance token) to be split to the child neuron. - #[prost(uint64, tag = "1")] pub amount_e8s: u64, /// The nonce that is used to compute the child neuron's /// subaccount which also serves as the child neuron's ID. This nonce /// is also used as the memo field in the ledger transfer that transfers /// the stake from the parent to the child neuron. - #[prost(uint64, tag = "2")] pub memo: u64, } /// The operation that merges a given percentage of a neuron's maturity (if applicable /// to the nervous system) to the neuron's stake. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct MergeMaturity { /// The percentage of maturity to merge, from 1 to 100. - #[prost(uint32, tag = "1")] pub percentage_to_merge: u32, } /// Stake the maturity of a neuron. /// The caller can choose a percentage of of the current maturity to stake. /// If 'percentage_to_stake' is not provided, all of the neuron's current /// maturity will be staked. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct StakeMaturity { /// The percentage of maturity to stake, from 1 to 100 (inclusive). - #[prost(uint32, optional, tag = "1")] - pub percentage_to_stake: ::core::option::Option, + pub percentage_to_stake: Option, } /// Disburse the maturity of a neuron to any ledger account. If an account /// is not specified, the caller's account will be used. The caller can choose /// a percentage of the current maturity to disburse to the ledger account. The /// resulting amount to disburse must be greater than or equal to the /// transaction fee. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct DisburseMaturity { /// The percentage to disburse, from 1 to 100 - #[prost(uint32, tag = "1")] pub percentage_to_disburse: u32, /// The (optional) principal to which to transfer the stake. - #[prost(message, optional, tag = "2")] - pub to_account: ::core::option::Option, + pub to_account: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct FinalizeDisburseMaturity { /// The amount to be disbursed in e8s of the governance token. - #[prost(uint64, tag = "1")] pub amount_to_be_disbursed_e8s: u64, /// The principal to which to transfer the stake (required). - #[prost(message, optional, tag = "2")] - pub to_account: ::core::option::Option, + pub to_account: Option, } /// The operation that adds a new follow relation to a neuron, specifying /// that it follows a set of followee neurons for a given proposal function. @@ -2546,85 +1733,42 @@ pub mod manage_neuron { /// then it becomes a catch-all follow rule, which will be used to vote /// automatically on proposals with actions for which no /// specific rule has been specified. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Follow { /// The function id of the proposal function defining for which proposals /// this follow relation is relevant. - #[prost(uint64, tag = "1")] pub function_id: u64, /// The list of followee neurons, specified by their neuron ID. - #[prost(message, repeated, tag = "2")] - pub followees: ::prost::alloc::vec::Vec, + pub followees: Vec, } /// The operation that registers a given vote from the neuron for a given /// proposal (a directly cast vote as opposed to a vote that is cast as /// a result of a follow relation). - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct RegisterVote { /// The ID of the proposal that the vote is cast for. - #[prost(message, optional, tag = "1")] - pub proposal: ::core::option::Option, + pub proposal: Option, /// The vote that is cast to adopt or reject the proposal. - #[prost(enumeration = "super::Vote", tag = "2")] pub vote: i32, } /// The operation that claims a new neuron (if it does not exist yet) or /// refreshes the stake of the neuron (if it already exists). - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ClaimOrRefresh { - #[prost(oneof = "claim_or_refresh::By", tags = "2, 3")] - pub by: ::core::option::Option, + pub by: Option, } /// Nested message and enum types in `ClaimOrRefresh`. pub mod claim_or_refresh { /// (see MemoAndController below) - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct MemoAndController { /// The memo(nonce) that is used to compute the neuron's subaccount /// (where the tokens were staked to). - #[prost(uint64, tag = "1")] pub memo: u64, /// The principal for which the neuron should be claimed. - #[prost(message, optional, tag = "2")] - pub controller: ::core::option::Option<::ic_base_types::PrincipalId>, + pub controller: Option<::ic_base_types::PrincipalId>, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum By { /// The memo and principal used to define the neuron to be claimed /// or refreshed. Specifically, the memo (nonce) and the given principal @@ -2633,12 +1777,10 @@ pub mod manage_neuron { /// refreshing a neuron were transferred to. /// If 'controller' is omitted, the id of the principal who calls this /// operation will be used. - #[prost(message, tag = "2")] MemoAndController(MemoAndController), /// The neuron ID of a neuron that should be refreshed. This just serves /// as an alternative way to specify a neuron to be refreshed, but cannot /// be used to claim new neurons. - #[prost(message, tag = "3")] NeuronId(super::super::Empty), } } @@ -2647,386 +1789,177 @@ pub mod manage_neuron { /// If the PrincipalId doesn't have existing permissions, a new entry will be added for it /// with the provided permissions. If a principalId already has permissions for the neuron, /// the new permissions will be added to the existing set. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct AddNeuronPermissions { /// The PrincipalId that the permissions will be granted to. - #[prost(message, optional, tag = "1")] - pub principal_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub principal_id: Option<::ic_base_types::PrincipalId>, /// The set of permissions that will be granted to the PrincipalId. - #[prost(message, optional, tag = "2")] - pub permissions_to_add: ::core::option::Option, + pub permissions_to_add: Option, } /// Remove a set of permissions from the Neuron for the given PrincipalId. If a PrincipalId has all of /// its permissions removed, it will be removed from the neuron's permissions list. This is a dangerous /// operation as its possible to remove all permissions for a neuron and no longer be able to modify /// it's state, i.e. disbursing the neuron back into the governance token. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct RemoveNeuronPermissions { /// The PrincipalId that the permissions will be revoked from. - #[prost(message, optional, tag = "1")] - pub principal_id: ::core::option::Option<::ic_base_types::PrincipalId>, + pub principal_id: Option<::ic_base_types::PrincipalId>, /// The set of permissions that will be revoked from the PrincipalId. - #[prost(message, optional, tag = "2")] - pub permissions_to_remove: ::core::option::Option, + pub permissions_to_remove: Option, } - #[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] + #[derive(candid::CandidType, candid::Deserialize, Debug)] #[allow(clippy::large_enum_variant)] - #[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq)] pub enum Command { - #[prost(message, tag = "2")] Configure(Configure), - #[prost(message, tag = "3")] Disburse(Disburse), - #[prost(message, tag = "4")] Follow(Follow), /// Making a proposal is defined by a proposal, which contains the proposer neuron. /// Making a proposal will implicitly cast a yes vote for the proposing neuron. - #[prost(message, tag = "5")] MakeProposal(super::Proposal), - #[prost(message, tag = "6")] RegisterVote(RegisterVote), - #[prost(message, tag = "7")] Split(Split), - #[prost(message, tag = "8")] ClaimOrRefresh(ClaimOrRefresh), - #[prost(message, tag = "9")] MergeMaturity(MergeMaturity), - #[prost(message, tag = "10")] DisburseMaturity(DisburseMaturity), - #[prost(message, tag = "11")] AddNeuronPermissions(AddNeuronPermissions), - #[prost(message, tag = "12")] RemoveNeuronPermissions(RemoveNeuronPermissions), - #[prost(message, tag = "13")] StakeMaturity(StakeMaturity), } } /// The response of a ManageNeuron command. /// There is a dedicated response type for each `ManageNeuron.command` field. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ManageNeuronResponse { - #[prost( - oneof = "manage_neuron_response::Command", - tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13" - )] - pub command: ::core::option::Option, + pub command: Option, } /// Nested message and enum types in `ManageNeuronResponse`. pub mod manage_neuron_response { /// The response to the ManageNeuron command 'configure'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct ConfigureResponse {} /// The response to the ManageNeuron command 'disburse'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct DisburseResponse { /// The block height of the ledger where the tokens were disbursed to the /// given account. - #[prost(uint64, tag = "1")] pub transfer_block_height: u64, } /// The response to the ManageNeuron command 'merge_maturity'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct MergeMaturityResponse { /// The maturity that was merged in fractions of /// 10E-8 of a governance token. - #[prost(uint64, tag = "1")] pub merged_maturity_e8s: u64, /// The resulting cached stake of the modified neuron /// in fractions of 10E-8 of a governance token. - #[prost(uint64, tag = "2")] pub new_stake_e8s: u64, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct DisburseMaturityResponse { /// This field is deprecated and is populated with the same value as `amount_deducted_e8s`. - #[prost(uint64, tag = "2")] pub amount_disbursed_e8s: u64, /// The amount of maturity in e8s of the governance token deducted from the Neuron. /// This amount will undergo maturity modulation if enabled, and may be increased or /// decreased at the time of disbursement. - #[prost(uint64, optional, tag = "3")] - pub amount_deducted_e8s: ::core::option::Option, + pub amount_deducted_e8s: Option, } - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct StakeMaturityResponse { - #[prost(uint64, tag = "1")] pub maturity_e8s: u64, - #[prost(uint64, tag = "2")] pub staked_maturity_e8s: u64, } /// The response to the ManageNeuron command 'follow'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct FollowResponse {} /// The response to the ManageNeuron command 'make_proposal'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct MakeProposalResponse { /// The ID of the created proposal. - #[prost(message, optional, tag = "1")] - pub proposal_id: ::core::option::Option, + pub proposal_id: Option, } /// The response to the ManageNeuron command 'register_vote'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct RegisterVoteResponse {} /// The response to the ManageNeuron command 'split'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct SplitResponse { /// The ID of the 'child neuron' that was newly created. - #[prost(message, optional, tag = "1")] - pub created_neuron_id: ::core::option::Option, + pub created_neuron_id: Option, } /// The response to the ManageNeuron command 'claim_or_refresh'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ClaimOrRefreshResponse { /// The neuron ID of the neuron that was newly claimed or /// refreshed. - #[prost(message, optional, tag = "1")] - pub refreshed_neuron_id: ::core::option::Option, + pub refreshed_neuron_id: Option, } /// The response to the ManageNeuron command 'add_neuron_permissions'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct AddNeuronPermissionsResponse {} /// The response to the ManageNeuron command 'remove_neuron_permissions'. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct RemoveNeuronPermissionsResponse {} - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum Command { - #[prost(message, tag = "1")] Error(super::GovernanceError), - #[prost(message, tag = "2")] Configure(ConfigureResponse), - #[prost(message, tag = "3")] Disburse(DisburseResponse), - #[prost(message, tag = "4")] Follow(FollowResponse), - #[prost(message, tag = "5")] MakeProposal(MakeProposalResponse), - #[prost(message, tag = "6")] RegisterVote(RegisterVoteResponse), - #[prost(message, tag = "7")] Split(SplitResponse), - #[prost(message, tag = "8")] ClaimOrRefresh(ClaimOrRefreshResponse), - #[prost(message, tag = "9")] MergeMaturity(MergeMaturityResponse), - #[prost(message, tag = "10")] DisburseMaturity(DisburseMaturityResponse), - #[prost(message, tag = "11")] AddNeuronPermission(AddNeuronPermissionsResponse), - #[prost(message, tag = "12")] RemoveNeuronPermission(RemoveNeuronPermissionsResponse), - #[prost(message, tag = "13")] StakeMaturity(StakeMaturityResponse), } } /// An operation that attempts to get a neuron by a given neuron ID. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetNeuron { - #[prost(message, optional, tag = "1")] - pub neuron_id: ::core::option::Option, + pub neuron_id: Option, } /// A response to the GetNeuron command. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetNeuronResponse { /// The response to a GetNeuron command is either an error or /// the requested neuron. - #[prost(oneof = "get_neuron_response::Result", tags = "1, 2")] - pub result: ::core::option::Option, + pub result: Option, } /// Nested message and enum types in `GetNeuronResponse`. pub mod get_neuron_response { /// The response to a GetNeuron command is either an error or /// the requested neuron. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum Result { - #[prost(message, tag = "1")] Error(super::GovernanceError), - #[prost(message, tag = "2")] Neuron(super::Neuron), } } -/// An operation that attempts to get a proposal by a given proposal ID. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +/// An operation that attempts to get a proposal by a given proposal ID. +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetProposal { - #[prost(message, optional, tag = "1")] - pub proposal_id: ::core::option::Option, + pub proposal_id: Option, } /// A response to the GetProposal command. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetProposalResponse { /// The response to a GetProposal command is either an error or /// the proposal data corresponding to the requested proposal. - #[prost(oneof = "get_proposal_response::Result", tags = "1, 2")] - pub result: ::core::option::Option, + pub result: Option, } /// Nested message and enum types in `GetProposalResponse`. pub mod get_proposal_response { /// The response to a GetProposal command is either an error or /// the proposal data corresponding to the requested proposal. - #[derive(candid::CandidType, candid::Deserialize, comparable::Comparable)] + #[derive(candid::CandidType, candid::Deserialize, Debug)] #[allow(clippy::large_enum_variant)] - #[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq)] pub enum Result { - #[prost(message, tag = "1")] Error(super::GovernanceError), - #[prost(message, tag = "2")] Proposal(super::ProposalData), } } @@ -3037,18 +1970,10 @@ pub mod get_proposal_response { /// Proposals are stored using an increasing id where the most recent proposals /// have the highest ids. ListProposals reverses the list and paginates backwards /// using `before_proposal`, so the first element returned is the latest proposal. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ListProposals { /// Limit the number of Proposals returned in each page, from 1 to 100. /// If a value outside of this range is provided, 100 will be used. - #[prost(uint32, tag = "1")] pub limit: u32, /// The proposal ID specifying which proposals to return. /// This should be set to the last proposal of the previously returned page and @@ -3056,12 +1981,10 @@ pub struct ListProposals { /// If this is specified, then only the proposals that have a proposal ID strictly /// lower than the specified one are returned. If this is not specified /// then the list of proposals starts with the most recent proposal's ID. - #[prost(message, optional, tag = "2")] - pub before_proposal: ::core::option::Option, + pub before_proposal: Option, /// A list of proposal types, specifying that proposals of the given /// types should be excluded in this list. - #[prost(uint64, repeated, tag = "3")] - pub exclude_type: ::prost::alloc::vec::Vec, + pub exclude_type: Vec, /// A list of proposal reward statuses, specifying that only proposals that /// that have one of the define reward statuses should be included /// in the list. @@ -3070,48 +1993,29 @@ pub struct ListProposals { /// Example: If users are only interested in proposals for which they can /// receive voting rewards they can use this to filter for proposals /// with reward status PROPOSAL_REWARD_STATUS_ACCEPT_VOTES. - #[prost(enumeration = "ProposalRewardStatus", repeated, tag = "4")] - pub include_reward_status: ::prost::alloc::vec::Vec, + pub include_reward_status: Vec, /// A list of proposal decision statuses, specifying that only proposals that /// that have one of the define decision statuses should be included /// in the list. /// If this list is empty, no restriction is applied. - #[prost(enumeration = "ProposalDecisionStatus", repeated, tag = "5")] - pub include_status: ::prost::alloc::vec::Vec, + pub include_status: Vec, } /// A response to the ListProposals command. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ListProposalsResponse { /// The returned list of proposals' ProposalData. - #[prost(message, repeated, tag = "1")] - pub proposals: ::prost::alloc::vec::Vec, + pub proposals: Vec, /// Whether ballots cast by the caller are included in the returned proposals. - #[prost(bool, optional, tag = "2")] - pub include_ballots_by_caller: ::core::option::Option, + pub include_ballots_by_caller: Option, } /// An operation that lists all neurons tracked in the Governance state in a /// paginated fashion. /// Listing of all neurons can be accomplished using `limit` and `start_page_at`. /// To only list neurons associated with a given principal, use `of_principal`. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ListNeurons { /// Limit the number of Neurons returned in each page, from 1 to 100. /// If a value outside of this range is provided, 100 will be used. - #[prost(uint32, tag = "1")] pub limit: u32, /// Used to indicate where the next page of Neurons should start. Should be /// set to the last neuron of the previously returned page and will not be @@ -3119,708 +2023,333 @@ pub struct ListNeurons { /// size limit starting at the "0th" Neuron. Neurons are not kept in any specific /// order, but their ordering is deterministic, so this can be used to return all /// the neurons one page at a time. - #[prost(message, optional, tag = "2")] - pub start_page_at: ::core::option::Option, + pub start_page_at: Option, /// A principal ID, specifying that only neurons for which this principal has /// any permissions should be included in the list. /// If this is not specified, no restriction is applied. - #[prost(message, optional, tag = "3")] - pub of_principal: ::core::option::Option<::ic_base_types::PrincipalId>, + pub of_principal: Option<::ic_base_types::PrincipalId>, } /// A response to the ListNeurons command. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ListNeuronsResponse { /// The returned list of neurons. - #[prost(message, repeated, tag = "1")] - pub neurons: ::prost::alloc::vec::Vec, + pub neurons: Vec, } /// The response to the list_nervous_system_functions query. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ListNervousSystemFunctionsResponse { /// Current set of nervous system function, both native and user-defined, /// that can be executed by proposal. - #[prost(message, repeated, tag = "1")] - pub functions: ::prost::alloc::vec::Vec, + pub functions: Vec, /// Set of nervous system function ids that are reserved and cannot be /// used to add new NervousSystemFunctions. - #[prost(uint64, repeated, tag = "2")] - pub reserved_ids: ::prost::alloc::vec::Vec, + pub reserved_ids: Vec, } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct SetMode { - #[prost(enumeration = "governance::Mode", tag = "1")] pub mode: i32, } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct SetModeResponse {} -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetMode {} -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetModeResponse { - #[prost(enumeration = "governance::Mode", optional, tag = "1")] - pub mode: ::core::option::Option, + pub mode: Option, } /// The request for the `claim_swap_neurons` method. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ClaimSwapNeuronsRequest { /// The set of parameters that define the neurons created in `claim_swap_neurons`. For /// each NeuronRecipe, one neuron will be created. - #[prost(message, optional, tag = "2")] - pub neuron_recipes: ::core::option::Option, + pub neuron_recipes: Option, } /// Nested message and enum types in `ClaimSwapNeuronsRequest`. pub mod claim_swap_neurons_request { /// Replacement for NeuronParameters. Contains the information needed to set up /// a neuron for a swap participant. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronRecipe { /// The principal that should be the controller of the SNS neuron - #[prost(message, optional, tag = "1")] - pub controller: ::core::option::Option<::ic_base_types::PrincipalId>, + pub controller: Option<::ic_base_types::PrincipalId>, /// The ID of the SNS neuron - #[prost(message, optional, tag = "2")] - pub neuron_id: ::core::option::Option, + pub neuron_id: Option, /// The SNS neuron's stake in e8s (10E-8 of a token) - #[prost(uint64, optional, tag = "3")] - pub stake_e8s: ::core::option::Option, + pub stake_e8s: Option, /// The duration in seconds that the neuron's dissolve delay will be set to. - #[prost(uint64, optional, tag = "4")] - pub dissolve_delay_seconds: ::core::option::Option, + pub dissolve_delay_seconds: Option, /// The neurons this neuron should follow - #[prost(message, optional, tag = "5")] - pub followees: ::core::option::Option, - #[prost(oneof = "neuron_recipe::Participant", tags = "6, 7")] - pub participant: ::core::option::Option, + pub followees: Option, + pub participant: Option, } /// Nested message and enum types in `NeuronRecipe`. pub mod neuron_recipe { /// The info that for a participant in the Neurons' Fund - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronsFund { /// The neuron ID of the NNS neuron that participated in the Neurons' Fund. - #[prost(uint64, optional, tag = "1")] - pub nns_neuron_id: ::core::option::Option, + pub nns_neuron_id: Option, /// The controller of the NNS neuron that participated in the Neurons' Fund. - #[prost(message, optional, tag = "2")] - pub nns_neuron_controller: ::core::option::Option<::ic_base_types::PrincipalId>, + pub nns_neuron_controller: Option<::ic_base_types::PrincipalId>, /// The hotkeys of the NNS neuron that participated in the Neurons' Fund. - #[prost(message, optional, tag = "3")] - pub nns_neuron_hotkeys: - ::core::option::Option<::ic_nervous_system_proto::pb::v1::Principals>, + pub nns_neuron_hotkeys: Option<::ic_nervous_system_proto::pb::v1::Principals>, } /// The info that for a direct participant #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq, )] pub struct Direct {} - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum Participant { - #[prost(message, tag = "6")] Direct(Direct), - #[prost(message, tag = "7")] NeuronsFund(NeuronsFund), } } /// Needed to cause prost to generate a type isomorphic to /// Optional>. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct NeuronRecipes { - #[prost(message, repeated, tag = "1")] - pub neuron_recipes: ::prost::alloc::vec::Vec, + pub neuron_recipes: Vec, } } /// The response for the `claim_swap_neurons` method. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ClaimSwapNeuronsResponse { /// ClaimSwapNeurons will either return an error, in which /// no requested neurons were claimed, or a vector with /// various neuron statuses for the requested neuron ids. - #[prost( - oneof = "claim_swap_neurons_response::ClaimSwapNeuronsResult", - tags = "4, 5" - )] - pub claim_swap_neurons_result: - ::core::option::Option, + pub claim_swap_neurons_result: Option, } /// Nested message and enum types in `ClaimSwapNeuronsResponse`. pub mod claim_swap_neurons_response { /// The ok result from `claim_swap_neurons. For every requested neuron, /// a SwapNeuron message is returned, and should equal the count of /// `ClaimSwapNeuronsRequest.neuron_recipes`. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct ClaimedSwapNeurons { - #[prost(message, repeated, tag = "1")] - pub swap_neurons: ::prost::alloc::vec::Vec, + pub swap_neurons: Vec, } /// SwapNeuron associates the status of a neuron attempting to be /// claimed with a NeuronId. The `id` field will correspond with a /// `ClaimSwapNeuronsRequest.neuron_recipes.neuron_id` field in /// the request object used in `claim_swap_neurons`. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, - )] + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct SwapNeuron { - #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, + pub id: Option, /// The status of claiming of a requested Sale neuron. - #[prost(enumeration = "super::ClaimedSwapNeuronStatus", tag = "2")] pub status: i32, } /// ClaimSwapNeurons will either return an error, in which /// no requested neurons were claimed, or a vector with /// various neuron statuses for the requested neuron ids. - #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Oneof, - )] + #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum ClaimSwapNeuronsResult { - #[prost(message, tag = "4")] Ok(ClaimedSwapNeurons), - #[prost(enumeration = "super::ClaimSwapNeuronsError", tag = "5")] Err(i32), } } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetMaturityModulationRequest {} -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetMaturityModulationResponse { - #[prost(message, optional, tag = "1")] - pub maturity_modulation: ::core::option::Option, + pub maturity_modulation: Option, } /// A request to add maturity to a neuron. The associated endpoint is only /// available when governance is compiled with the `test` feature enabled. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct AddMaturityRequest { - #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, - #[prost(uint64, optional, tag = "2")] - pub amount_e8s: ::core::option::Option, + pub id: Option, + pub amount_e8s: Option, } /// The response to a request to add maturity to a neuron. The associated endpoint is only /// available when governance is compiled with the `test` feature enabled. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct AddMaturityResponse { - #[prost(uint64, optional, tag = "1")] - pub new_maturity_e8s: ::core::option::Option, + pub new_maturity_e8s: Option, } /// A test-only API that advances the target version of the SNS. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct AdvanceTargetVersionRequest { - #[prost(message, optional, tag = "1")] - pub target_version: ::core::option::Option, + pub target_version: Option, } /// The response to a request to advance the target version of the SNS. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct AdvanceTargetVersionResponse {} /// A test-only API that refreshes the cached upgrade steps. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct RefreshCachedUpgradeStepsRequest {} /// The response to a request to refresh the cached upgrade steps. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct RefreshCachedUpgradeStepsResponse {} /// Represents a single entry in the upgrade journal. #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeJournalEntry { - #[prost(uint64, optional, tag = "6")] - pub timestamp_seconds: ::core::option::Option, - #[prost(oneof = "upgrade_journal_entry::Event", tags = "1, 7, 2, 3, 4, 5")] - pub event: ::core::option::Option, + pub timestamp_seconds: Option, + pub event: Option, } /// Nested message and enum types in `UpgradeJournalEntry`. pub mod upgrade_journal_entry { #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeStepsRefreshed { - #[prost(message, optional, tag = "2")] - pub upgrade_steps: ::core::option::Option, + pub upgrade_steps: Option, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeStepsReset { - #[prost(string, optional, tag = "1")] - pub human_readable: ::core::option::Option<::prost::alloc::string::String>, - #[prost(message, optional, tag = "2")] - pub upgrade_steps: ::core::option::Option, + pub human_readable: Option, + pub upgrade_steps: Option, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct TargetVersionSet { - #[prost(message, optional, tag = "1")] - pub old_target_version: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub new_target_version: ::core::option::Option, + pub old_target_version: Option, + pub new_target_version: Option, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct TargetVersionReset { - #[prost(message, optional, tag = "1")] - pub old_target_version: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub new_target_version: ::core::option::Option, - #[prost(string, optional, tag = "3")] - pub human_readable: ::core::option::Option<::prost::alloc::string::String>, + pub old_target_version: Option, + pub new_target_version: Option, + pub human_readable: Option, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeStarted { - #[prost(message, optional, tag = "1")] - pub current_version: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub expected_version: ::core::option::Option, - #[prost(oneof = "upgrade_started::Reason", tags = "3, 4")] - pub reason: ::core::option::Option, + pub current_version: Option, + pub expected_version: Option, + pub reason: Option, } /// Nested message and enum types in `UpgradeStarted`. pub mod upgrade_started { #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - Copy, - PartialEq, - ::prost::Oneof, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, Copy, PartialEq, )] pub enum Reason { - #[prost(message, tag = "3")] UpgradeSnsToNextVersionProposal(super::super::ProposalId), - #[prost(message, tag = "4")] BehindTargetVersion(super::super::Empty), } } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeOutcome { - #[prost(string, optional, tag = "1")] - pub human_readable: ::core::option::Option<::prost::alloc::string::String>, - #[prost(oneof = "upgrade_outcome::Status", tags = "2, 3, 4, 5")] - pub status: ::core::option::Option, + pub human_readable: Option, + pub status: Option, } /// Nested message and enum types in `UpgradeOutcome`. pub mod upgrade_outcome { #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct InvalidState { - #[prost(message, optional, tag = "1")] - pub version: ::core::option::Option, + pub version: Option, } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Oneof, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub enum Status { - #[prost(message, tag = "2")] Success(super::super::Empty), - #[prost(message, tag = "3")] Timeout(super::super::Empty), /// The SNS ended up being upgraded to a version that was not the expected one. - #[prost(message, tag = "4")] InvalidState(InvalidState), - #[prost(message, tag = "5")] ExternalFailure(super::super::Empty), } } #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Oneof, + candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub enum Event { - #[prost(message, tag = "1")] UpgradeStepsRefreshed(UpgradeStepsRefreshed), - #[prost(message, tag = "7")] UpgradeStepsReset(UpgradeStepsReset), - #[prost(message, tag = "2")] TargetVersionSet(TargetVersionSet), - #[prost(message, tag = "3")] TargetVersionReset(TargetVersionReset), - #[prost(message, tag = "4")] UpgradeStarted(UpgradeStarted), - #[prost(message, tag = "5")] UpgradeOutcome(UpgradeOutcome), } } /// Needed to cause prost to generate a type isomorphic to Option>. #[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - serde::Serialize, - Clone, - PartialEq, - ::prost::Message, + Default, candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq, )] pub struct UpgradeJournal { /// The entries in the upgrade journal. - #[prost(message, repeated, tag = "1")] - pub entries: ::prost::alloc::vec::Vec, + pub entries: Vec, } /// The upgrade journal contains all the information neede to audit previous SNS upgrades and understand its current state. /// It is being implemented as part of the "effortless SNS upgrade" feature. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct GetUpgradeJournalRequest { /// Maximum number of journal entries to return. /// If not specified, defaults to 100. Values larger than 100 will be capped at 100. - #[prost(uint64, optional, tag = "1")] - pub limit: ::core::option::Option, + pub limit: Option, /// The starting index from which to return entries, counting from the oldest entry (0). /// If not specified, return the most recent entries. - #[prost(uint64, optional, tag = "2")] - pub offset: ::core::option::Option, + pub offset: Option, } -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GetUpgradeJournalResponse { - #[prost(message, optional, tag = "1")] - pub upgrade_steps: ::core::option::Option, - #[prost(uint64, optional, tag = "2")] - pub response_timestamp_seconds: ::core::option::Option, + pub upgrade_steps: Option, + pub response_timestamp_seconds: Option, /// The target version that the SNS will be upgraded to. /// Currently, this field is always None, but in the "effortless SNS upgrade" /// feature, it reflect the version of the SNS that the community has decided to upgrade to. - #[prost(message, optional, tag = "3")] - pub target_version: ::core::option::Option, - #[prost(message, optional, tag = "5")] - pub deployed_version: ::core::option::Option, - #[prost(message, optional, tag = "4")] - pub upgrade_journal: ::core::option::Option, - #[prost(uint64, optional, tag = "6")] - pub upgrade_journal_entry_count: ::core::option::Option, + pub target_version: Option, + pub deployed_version: Option, + pub upgrade_journal: Option, + pub upgrade_journal_entry_count: Option, } /// A request to mint tokens for a particular principal. The associated endpoint /// is only available on SNS governance, and only then when SNS governance is /// compiled with the `test` feature enabled. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct MintTokensRequest { - #[prost(message, optional, tag = "1")] - pub recipient: ::core::option::Option, - #[prost(uint64, optional, tag = "2")] - pub amount_e8s: ::core::option::Option, + pub recipient: Option, + pub amount_e8s: Option, } /// The response to a request to mint tokens for a particular principal. The /// associated endpoint is only available on SNS governance, and only then when /// SNS governance is compiled with the `test` feature enabled. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - Copy, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)] pub struct MintTokensResponse {} /// A Ledger subaccount. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Subaccount { - #[prost(bytes = "vec", tag = "1")] #[serde(with = "serde_bytes")] - pub subaccount: ::prost::alloc::vec::Vec, + pub subaccount: Vec, } /// A Ledger account identified by the owner of the account `of` and /// the `subaccount`. If the `subaccount` is not specified then the default /// one is used. -#[derive( - candid::CandidType, - candid::Deserialize, - comparable::Comparable, - Clone, - PartialEq, - ::prost::Message, -)] +#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct Account { /// The owner of the account. - #[prost(message, optional, tag = "1")] - pub owner: ::core::option::Option<::ic_base_types::PrincipalId>, + pub owner: Option<::ic_base_types::PrincipalId>, /// The subaccount of the account. If not set then the default /// subaccount (all bytes set to 0) is used. - #[prost(message, optional, tag = "2")] - pub subaccount: ::core::option::Option, + pub subaccount: Option, } /// The different types of neuron permissions, i.e., privileges to modify a neuron, /// that principals can have. #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, clap::ValueEnum, - strum_macros::EnumIter, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum NeuronPermissionType { @@ -3877,7 +2406,7 @@ impl NeuronPermissionType { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "NEURON_PERMISSION_TYPE_UNSPECIFIED" => Some(Self::Unspecified), "NEURON_PERMISSION_TYPE_CONFIGURE_DISSOLVE_STATE" => Some(Self::ConfigureDissolveState), @@ -3898,16 +2427,14 @@ impl NeuronPermissionType { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum Vote { @@ -3933,7 +2460,7 @@ impl Vote { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "VOTE_UNSPECIFIED" => Some(Self::Unspecified), "VOTE_YES" => Some(Self::Yes), @@ -3945,16 +2472,14 @@ impl Vote { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum LogVisibility { @@ -3977,7 +2502,7 @@ impl LogVisibility { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "LOG_VISIBILITY_UNSPECIFIED" => Some(Self::Unspecified), "LOG_VISIBILITY_CONTROLLERS" => Some(Self::Controllers), @@ -3989,16 +2514,14 @@ impl LogVisibility { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum ProposalDecisionStatus { @@ -4031,7 +2554,7 @@ impl ProposalDecisionStatus { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "PROPOSAL_DECISION_STATUS_UNSPECIFIED" => Some(Self::Unspecified), "PROPOSAL_DECISION_STATUS_OPEN" => Some(Self::Open), @@ -4047,16 +2570,14 @@ impl ProposalDecisionStatus { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum ProposalRewardStatus { @@ -4088,7 +2609,7 @@ impl ProposalRewardStatus { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "PROPOSAL_REWARD_STATUS_UNSPECIFIED" => Some(Self::Unspecified), "PROPOSAL_REWARD_STATUS_ACCEPT_VOTES" => Some(Self::AcceptVotes), @@ -4105,16 +2626,14 @@ impl ProposalRewardStatus { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum ClaimedSwapNeuronStatus { @@ -4154,7 +2673,7 @@ impl ClaimedSwapNeuronStatus { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "CLAIMED_SWAP_NEURON_STATUS_UNSPECIFIED" => Some(Self::Unspecified), "CLAIMED_SWAP_NEURON_STATUS_SUCCESS" => Some(Self::Success), @@ -4170,16 +2689,14 @@ impl ClaimedSwapNeuronStatus { #[derive( candid::CandidType, candid::Deserialize, - comparable::Comparable, + Debug, Clone, Copy, - Debug, PartialEq, Eq, Hash, PartialOrd, Ord, - ::prost::Enumeration, )] #[repr(i32)] pub enum ClaimSwapNeuronsError { @@ -4206,7 +2723,7 @@ impl ClaimSwapNeuronsError { } } /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { + pub fn from_str_name(value: &str) -> Option { match value { "CLAIM_SWAP_NEURONS_ERROR_UNSPECIFIED" => Some(Self::Unspecified), "CLAIM_SWAP_NEURONS_ERROR_UNAUTHORIZED" => Some(Self::Unauthorized), diff --git a/rs/state_machine_tests/src/lib.rs b/rs/state_machine_tests/src/lib.rs index 87eb8cf6e70..5031290b05a 100644 --- a/rs/state_machine_tests/src/lib.rs +++ b/rs/state_machine_tests/src/lib.rs @@ -153,9 +153,8 @@ use ic_types::{ CanisterId, CryptoHashOfState, Cycles, NumBytes, PrincipalId, SubnetId, UserId, }; use ic_xnet_payload_builder::{ - certified_slice_pool::{certified_slice_count_bytes, CertifiedSliceError}, - ExpectedIndices, RefillTaskHandle, XNetPayloadBuilderImpl, XNetPayloadBuilderMetrics, - XNetSlicePool, + certified_slice_pool::CertifiedSlicePool, refill_stream_slice_indices, RefillTaskHandle, + XNetPayloadBuilderImpl, XNetPayloadBuilderMetrics, XNetSlicePoolImpl, }; use rcgen::{CertificateParams, KeyPair}; use serde::Deserialize; @@ -599,72 +598,64 @@ pub trait Subnets: Send + Sync { fn get(&self, subnet_id: SubnetId) -> Option>; } -/// Struct mocking the pool of XNet messages required for -/// instantiating `XNetPayloadBuilderImpl` in `StateMachine`. -struct PocketXNetSlicePoolImpl { - /// Pool of `StateMachine`s from which the XNet messages are fetched. +/// Struct mocking the XNet layer. +struct PocketXNetImpl { + /// Pool of `StateMachine`s from which XNet messages are fetched. subnets: Arc, - /// Subnet ID of the `StateMachine` containing the pool. + /// The certified slice pool of the `StateMachine` for which the XNet layer is mocked. + pool: Arc>, + /// The subnet ID of the `StateMachine` for which the XNet layer is mocked. own_subnet_id: SubnetId, } -impl PocketXNetSlicePoolImpl { - fn new(subnets: Arc, own_subnet_id: SubnetId) -> Self { +impl PocketXNetImpl { + fn new( + subnets: Arc, + pool: Arc>, + own_subnet_id: SubnetId, + ) -> Self { Self { subnets, + pool, own_subnet_id, } } -} -impl XNetSlicePool for PocketXNetSlicePoolImpl { - /// Obtains a certified slice of a stream from a `StateMachine` - /// corresponding to a given subnet ID. - fn take_slice( - &self, - subnet_id: SubnetId, - begin: Option<&ExpectedIndices>, - msg_limit: Option, - byte_limit: Option, - ) -> Result, CertifiedSliceError> { - let sm = self.subnets.get(subnet_id).unwrap(); - let msg_begin = begin.map(|idx| idx.message_index); - // We set `witness_begin` equal to `msg_begin` since all states are certified. - let certified_stream = sm.generate_certified_stream_slice( - self.own_subnet_id, - msg_begin, - msg_begin, - msg_limit, - byte_limit, - ); - Ok(certified_stream - .map(|certified_stream| { - let mut num_bytes = certified_slice_count_bytes(&certified_stream).unwrap(); - // Because `StateMachine::generate_certified_stream_slice` only uses a size estimate - // when constructing a slice (this estimate can be off by at most a few KB), - // we fake the reported slice size if it exceeds the specified size limit to make sure the payload builder will accept the slice as valid and include it into the block. - // This is fine since we don't actually validate the payload in the context of Pocket IC, and so blocks containing - // a XNet slice exceeding the byte limit won't be rejected as invalid. - if let Some(byte_limit) = byte_limit { - if num_bytes > byte_limit { - num_bytes = byte_limit; + fn refill(&self, registry_version: RegistryVersion, log: ReplicaLogger) { + let refill_stream_slice_indices = + refill_stream_slice_indices(self.pool.clone(), self.own_subnet_id); + + for (subnet_id, indices) in refill_stream_slice_indices { + let sm = self.subnets.get(subnet_id).unwrap(); + match sm.generate_certified_stream_slice( + self.own_subnet_id, + Some(indices.witness_begin), + Some(indices.msg_begin), + None, + Some(indices.byte_limit), + ) { + Ok(slice) => { + if indices.witness_begin != indices.msg_begin { + // Pulled a stream suffix, append to pooled slice. + self.pool + .lock() + .unwrap() + .append(subnet_id, slice, registry_version, log.clone()) + .unwrap(); + } else { + // Pulled a complete stream, replace pooled slice (if any). + self.pool + .lock() + .unwrap() + .put(subnet_id, slice, registry_version, log.clone()) + .unwrap(); } } - (certified_stream, num_bytes) - }) - .ok()) + Err(EncodeStreamError::NoStreamForSubnet(_)) => (), + Err(err) => panic!("Unexpected XNetClient error: {}", err), + } + } } - - /// We do not collect any metrics here. - fn observe_pool_size_bytes(&self) {} - - /// We do not cache XNet messages in this mock implementation - /// and thus there is no need for garbage collection. - fn garbage_collect(&self, _new_stream_positions: BTreeMap) {} - - /// We do not cache XNet messages in this mock implementation - /// and thus there is no need for garbage collection. - fn garbage_collect_slice(&self, _subnet_id: SubnetId, _stream_position: ExpectedIndices) {} } /// A custom `QueryStatsPayloadBuilderImpl` that uses a single @@ -825,6 +816,7 @@ pub struct StateMachine { ingress_pool: Arc>, ingress_manager: Arc, pub ingress_filter: Arc>, + pocket_xnet: Arc>>, payload_builder: Arc>>, message_routing: SyncMessageRouting, pub metrics_registry: MetricsRegistry, @@ -1224,7 +1216,12 @@ impl StateMachineBuilder { // Instantiate a `XNetPayloadBuilderImpl`. // We need to use a deterministic PRNG - so we use an arbitrary fixed seed, e.g., 42. let rng = Arc::new(Some(Mutex::new(StdRng::seed_from_u64(42)))); - let xnet_slice_pool_impl = Box::new(PocketXNetSlicePoolImpl::new(subnets, subnet_id)); + let certified_stream_store: Arc = sm.state_manager.clone(); + let certified_slice_pool = Arc::new(Mutex::new(CertifiedSlicePool::new( + certified_stream_store, + &sm.metrics_registry, + ))); + let xnet_slice_pool_impl = Box::new(XNetSlicePoolImpl::new(certified_slice_pool.clone())); let metrics = Arc::new(XNetPayloadBuilderMetrics::new(&sm.metrics_registry)); let xnet_payload_builder = Arc::new(XNetPayloadBuilderImpl::new_from_components( sm.state_manager.clone(), @@ -1262,6 +1259,10 @@ impl StateMachineBuilder { sm.replica_logger.clone(), )); + // Put `PocketXNetImpl` into `StateMachine` + // which contains no `PocketXNetImpl` after creation. + let pocket_xnet_impl = PocketXNetImpl::new(subnets, certified_slice_pool, subnet_id); + *sm.pocket_xnet.write().unwrap() = Some(pocket_xnet_impl); // Instantiate a `PayloadBuilderImpl` and put it into `StateMachine` // which contains no `PayloadBuilderImpl` after creation. *sm.payload_builder.write().unwrap() = Some(PayloadBuilderImpl::new( @@ -1305,6 +1306,7 @@ impl StateMachine { /// because the payload builder contains an `Arc` of this `StateMachine` /// which creates a circular dependency preventing this `StateMachine`s from being dropped. pub fn drop_payload_builder(&self) { + self.pocket_xnet.write().unwrap().take(); self.payload_builder.write().unwrap().take(); } @@ -1349,6 +1351,12 @@ impl StateMachine { membership_version: subnet_record.clone(), context_version: subnet_record, }; + self.pocket_xnet + .read() + .unwrap() + .as_ref() + .unwrap() + .refill(registry_version, self.replica_logger.clone()); let payload_builder = self.payload_builder.read().unwrap(); let payload_builder = payload_builder.as_ref().unwrap(); let batch_payload = payload_builder.get_payload( @@ -1775,6 +1783,7 @@ impl StateMachine { ingress_pool, ingress_manager: ingress_manager.clone(), ingress_filter: Arc::new(Mutex::new(execution_services.ingress_filter)), + pocket_xnet: Arc::new(RwLock::new(None)), // set by `StateMachineBuilder::build_with_subnets` payload_builder: Arc::new(RwLock::new(None)), // set by `StateMachineBuilder::build_with_subnets` ingress_history_reader: execution_services.ingress_history_reader, message_routing, @@ -1805,7 +1814,7 @@ impl StateMachine { } } - fn into_components(self) -> (Box, u64, Time, u64) { + fn into_components_inner(self) -> (Box, u64, Time, u64) { ( self.state_dir, self.nonce.into_inner(), @@ -1814,6 +1823,23 @@ impl StateMachine { ) } + fn into_components(self) -> (Box, u64, Time, u64) { + let state_manager = Arc::downgrade(&self.state_manager); + let result = self.into_components_inner(); + let mut i = 0i32; + // StateManager is owned by an Arc, that is cloned into multiple components and different + // threads. If we return before all the asynchronous components release the Arc, we may + // end up with to StateManagers writing to the same directory, resulting in a crash. + while state_manager.upgrade().is_some() { + std::thread::sleep(std::time::Duration::from_millis(50)); + i += 1; + if i >= 100 { + panic!("Failed to wait for StateManager drop"); + } + } + result + } + /// Emulates a node restart, including checkpoint recovery. pub fn restart_node(self) -> Self { // We must drop self before setup_form_dir so that we don't have two StateManagers pointing diff --git a/rs/state_manager/tests/state_manager.rs b/rs/state_manager/tests/state_manager.rs index 078e82a6d7f..b82e7b2aceb 100644 --- a/rs/state_manager/tests/state_manager.rs +++ b/rs/state_manager/tests/state_manager.rs @@ -6201,6 +6201,7 @@ fn can_merge_unexpected_number_of_files() { .vmemory_0(); let existing_overlays = pm_layout.existing_overlays().unwrap(); assert_eq!(existing_overlays.len(), NUM_PAGES); // single page per shard + state_manager.flush_tip_channel(); // Copy each shard for heights 1..HEIGHT; now each file is beyond the hard limit, // triggering forced merge for all shards back to one overlay. @@ -7519,8 +7520,12 @@ fn arbitrary_test_canister_op() -> impl Strategy { } proptest! { -// We go for fewer, but longer runs -#![proptest_config(ProptestConfig::with_cases(5))] +#![proptest_config(ProptestConfig { + // Fork to prevent flaky timeouts due to closed sandbox fds + fork: true, + // We go for fewer, but longer runs + ..ProptestConfig::with_cases(5) +})] #[test] fn random_canister_input_lsmt(ops in proptest::collection::vec(arbitrary_test_canister_op(), 1..50)) { diff --git a/rs/system_api/src/lib.rs b/rs/system_api/src/lib.rs index 4a0c6575bc3..4925252e6f7 100644 --- a/rs/system_api/src/lib.rs +++ b/rs/system_api/src/lib.rs @@ -1639,12 +1639,7 @@ impl SystemApi for SystemApiImpl { } fn get_num_instructions_from_bytes(&self, num_bytes: NumBytes) -> NumInstructions { - match self.sandbox_safe_system_state.subnet_type { - SubnetType::System => NumInstructions::from(0), - SubnetType::VerifiedApplication | SubnetType::Application => { - NumInstructions::from(num_bytes.get()) - } - } + NumInstructions::from(num_bytes.get()) } fn stable_memory_dirty_pages(&self) -> Vec<(PageIndex, &PageBytes)> { diff --git a/rs/tests/boundary_nodes/BUILD.bazel b/rs/tests/boundary_nodes/BUILD.bazel index 6916aa14f96..058bb5ed0a2 100644 --- a/rs/tests/boundary_nodes/BUILD.bazel +++ b/rs/tests/boundary_nodes/BUILD.bazel @@ -10,6 +10,7 @@ TEST_CANISTERS_RUNTIME_DEPS = [ "//rs/tests/test_canisters/http_counter", "//rs/tests/test_canisters/kv_store", "@asset_canister//file", + "@long_asset_canister//file", ] system_test_nns( @@ -18,6 +19,7 @@ system_test_nns( "KV_STORE_WASM_PATH": "$(rootpath //rs/tests/test_canisters/kv_store)", "HTTP_COUNTER_WASM_PATH": "$(rootpath //rs/tests/test_canisters/http_counter)", "ASSET_CANISTER_WASM_PATH": "$(rootpath @asset_canister//file)", + "LONG_ASSET_CANISTER_WASM_PATH": "$(rootpath @long_asset_canister//file)", }, extra_head_nns_tags = [], # don't run the head_nns variant on nightly since it aleady runs on long_test. tags = [ @@ -59,6 +61,7 @@ system_test_nns( "KV_STORE_WASM_PATH": "$(rootpath //rs/tests/test_canisters/kv_store)", "HTTP_COUNTER_WASM_PATH": "$(rootpath //rs/tests/test_canisters/http_counter)", "ASSET_CANISTER_WASM_PATH": "$(rootpath @asset_canister//file)", + "LONG_ASSET_CANISTER_WASM_PATH": "$(rootpath @long_asset_canister//file)", }, flaky = True, tags = [ diff --git a/rs/tests/boundary_nodes/bn_integration_on_playnet_test.rs b/rs/tests/boundary_nodes/bn_integration_on_playnet_test.rs index 5e33e17da73..32c8dde0658 100644 --- a/rs/tests/boundary_nodes/bn_integration_on_playnet_test.rs +++ b/rs/tests/boundary_nodes/bn_integration_on_playnet_test.rs @@ -4,9 +4,10 @@ use anyhow::Result; use ic_boundary_nodes_integration_test_common::{ api_call_test, api_canister_read_state_test, api_query_test, api_status_test, - api_subnet_read_state_test, api_sync_call_test, asset_canister_test, canister_denylist_test, - content_type_headers_test, cors_headers_test, http_endpoints_test, proxy_http_canister_test, - redirect_http_to_https_test, redirect_to_dashboard_test, + api_subnet_read_state_test, api_sync_call_test, canister_denylist_test, + content_type_headers_test, cors_headers_test, http_endpoints_test, legacy_asset_canister_test, + long_asset_canister_test, proxy_http_canister_test, redirect_http_to_https_test, + redirect_to_dashboard_test, }; use ic_boundary_nodes_system_test_utils::{ constants::BOUNDARY_NODE_NAME, helpers::BoundaryNodeHttpsConfig, setup::setup_ic_with_bn, @@ -34,7 +35,8 @@ fn main() -> Result<()> { .add_test(systest!(api_sync_call_test)) .add_test(systest!(api_canister_read_state_test)) .add_test(systest!(api_subnet_read_state_test)) - .add_test(systest!(asset_canister_test)) + .add_test(systest!(legacy_asset_canister_test)) + .add_test(systest!(long_asset_canister_test)) .add_test(systest!(content_type_headers_test)) .add_test(systest!(cors_headers_test)) .add_test(systest!(proxy_http_canister_test)) diff --git a/rs/tests/boundary_nodes/bn_integration_test.rs b/rs/tests/boundary_nodes/bn_integration_test.rs index 7c858087557..8a3100593b6 100644 --- a/rs/tests/boundary_nodes/bn_integration_test.rs +++ b/rs/tests/boundary_nodes/bn_integration_test.rs @@ -4,9 +4,10 @@ use anyhow::Result; use ic_boundary_nodes_integration_test_common::{ api_call_test, api_canister_read_state_test, api_query_test, api_status_test, - api_subnet_read_state_test, api_sync_call_test, asset_canister_test, canister_denylist_test, - content_type_headers_test, cors_headers_test, http_endpoints_test, proxy_http_canister_test, - redirect_http_to_https_test, redirect_to_dashboard_test, + api_subnet_read_state_test, api_sync_call_test, canister_denylist_test, + content_type_headers_test, cors_headers_test, http_endpoints_test, legacy_asset_canister_test, + long_asset_canister_test, proxy_http_canister_test, redirect_http_to_https_test, + redirect_to_dashboard_test, }; use ic_boundary_nodes_system_test_utils::{ constants::BOUNDARY_NODE_NAME, helpers::BoundaryNodeHttpsConfig, setup::setup_ic_with_bn, @@ -34,9 +35,10 @@ fn main() -> Result<()> { .add_test(systest!(api_sync_call_test)) .add_test(systest!(api_canister_read_state_test)) .add_test(systest!(api_subnet_read_state_test)) - .add_test(systest!(asset_canister_test)) .add_test(systest!(content_type_headers_test)) .add_test(systest!(cors_headers_test)) + .add_test(systest!(legacy_asset_canister_test)) + .add_test(systest!(long_asset_canister_test)) .add_test(systest!(proxy_http_canister_test)) .add_test(systest!(redirect_http_to_https_test)) .add_test(systest!(redirect_to_dashboard_test)) diff --git a/rs/tests/boundary_nodes/custom_domains/setup.rs b/rs/tests/boundary_nodes/custom_domains/setup.rs index ddd2ff996ee..c614b003412 100644 --- a/rs/tests/boundary_nodes/custom_domains/setup.rs +++ b/rs/tests/boundary_nodes/custom_domains/setup.rs @@ -883,7 +883,7 @@ pub async fn setup_asset_canister( index_content: Option<&str>, ) -> Result { let asset_canister = env - .deploy_asset_canister() + .deploy_legacy_asset_canister() .await .expect("Could not install asset canister"); diff --git a/rs/tests/boundary_nodes/integration_test_common/src/lib.rs b/rs/tests/boundary_nodes/integration_test_common/src/lib.rs index 84fb9a56cb8..0553cfef2ed 100644 --- a/rs/tests/boundary_nodes/integration_test_common/src/lib.rs +++ b/rs/tests/boundary_nodes/integration_test_common/src/lib.rs @@ -345,7 +345,7 @@ Coverage:: asset Canisters behave as expected end::catalog[] */ -pub fn asset_canister_test(env: TestEnv) { +pub fn legacy_asset_canister_test(env: TestEnv) { let logger_orig = env.logger(); let boundary_node = env .get_deployed_boundary_node(BOUNDARY_NODE_NAME) @@ -357,7 +357,7 @@ pub fn asset_canister_test(env: TestEnv) { info!(&logger_orig, "Creating asset canister"); let asset_canister_orig = rt - .block_on(env.deploy_asset_canister()) + .block_on(env.deploy_legacy_asset_canister()) .expect("Could not install asset canister"); let http_client_builder = ClientBuilder::new(); @@ -754,6 +754,150 @@ pub fn asset_canister_test(env: TestEnv) { .expect("test suite failed"); } +// Constants copied from long asset canister: +const ASSET_CHUNK_SIZE: usize = 2_000_000; + +const ONE_CHUNK_ASSET_LEN: usize = ASSET_CHUNK_SIZE; +const TWO_CHUNKS_ASSET_LEN: usize = ASSET_CHUNK_SIZE + 1; +const SIX_CHUNKS_ASSET_LEN: usize = 5 * ASSET_CHUNK_SIZE + 12; + +pub fn long_asset_canister_test(env: TestEnv) { + let logger_orig = env.logger(); + let boundary_node = env + .get_deployed_boundary_node(BOUNDARY_NODE_NAME) + .unwrap() + .get_snapshot() + .unwrap(); + + let rt = runtime(); + + info!(&logger_orig, "Creating asset canister"); + let asset_canister_orig = rt + .block_on(env.deploy_long_asset_canister()) + .expect("Could not install asset canister"); + + let http_client_builder = ClientBuilder::new(); + let (client_builder, host_orig) = if let Some(playnet) = boundary_node.get_playnet() { + ( + http_client_builder, + format!("{0}.{playnet}", asset_canister_orig.canister_id), + ) + } else { + let host = format!("{0}.ic0.app", asset_canister_orig.canister_id); + let bn_addr = SocketAddrV6::new(boundary_node.ipv6(), 0, 0, 0).into(); + let client_builder = http_client_builder + .danger_accept_invalid_certs(true) + .resolve(&host, bn_addr); + (client_builder, host) + }; + let http_client = client_builder.build().unwrap(); + + let futs = FuturesUnordered::new(); + futs.push(rt.spawn({ + let host = host_orig.clone(); + let logger = logger_orig.clone(); + let http_client = http_client.clone(); + let name = "Requesting a single chunk asset"; + info!(&logger, "Starting subtest {}", name); + + async move { + info!(&logger, "Requesting /long_asset_one_chunk ..."); + let res = http_client + .get(format!("https://{host}/long_asset_one_chunk")) + .header("accept-encoding", "gzip") + .send() + .await? + .bytes() + .await? + .to_vec(); + + if res.len() != ONE_CHUNK_ASSET_LEN { + bail!("/long_asset_one_chunk response did not match uploaded content") + } + + Ok(()) + } + })); + + futs.push(rt.spawn({ + let host = host_orig.clone(); + let logger = logger_orig.clone(); + let http_client = http_client.clone(); + let name = "Requesting a two chunk asset"; + info!(&logger, "Starting subtest {}", name); + + async move { + info!(&logger, "Requesting /long_asset_two_chunks ..."); + let res = http_client + .get(format!("https://{host}/long_asset_two_chunks")) + .header("accept-encoding", "gzip") + .send() + .await? + .bytes() + .await? + .to_vec(); + + if res.len() != TWO_CHUNKS_ASSET_LEN { + bail!("/long_asset_two_chunks response did not match uploaded content") + } + + Ok(()) + } + })); + + futs.push(rt.spawn({ + let host = host_orig.clone(); + let logger = logger_orig.clone(); + let http_client = http_client.clone(); + let name = "Requesting a six chunk asset"; + info!(&logger, "Starting subtest {}", name); + + async move { + info!(&logger, "Requesting /long_asset_six_chunks ..."); + let res = http_client + .get(format!("https://{host}/long_asset_six_chunks")) + .header("accept-encoding", "gzip") + .send() + .await? + .bytes() + .await? + .to_vec(); + + if res.len() != SIX_CHUNKS_ASSET_LEN { + bail!("/long_asset_six_chunks response did not match uploaded content") + } + + Ok(()) + } + })); + + let logger = logger_orig.clone(); + rt.block_on(async move { + let mut cnt_err = 0; + info!(&logger, "Waiting for subtests"); + + for fut in futs { + match fut.await { + Ok(Err(err)) => { + error!(logger, "test failed: {}", err); + cnt_err += 1; + } + Err(err) => { + error!(logger, "test panicked: {}", err); + cnt_err += 1; + } + _ => {} + } + } + + match cnt_err { + 0 => Ok(()), + _ => bail!("failed with {cnt_err} errors"), + } + }) + .expect("test suite failed"); +} + /* tag::catalog[] Title:: Boundary nodes HTTP canister test @@ -1325,7 +1469,7 @@ pub fn http_endpoints_test(env: TestEnv) { let rt = runtime(); info!(&logger_orig, "Creating asset canister"); - let asset_canister_orig = rt.block_on(env.deploy_asset_canister()).unwrap(); + let asset_canister_orig = rt.block_on(env.deploy_legacy_asset_canister()).unwrap(); info!(&logger_orig, "Uploading static assets"); #[derive(Clone)] diff --git a/rs/tests/driver/src/driver/asset_canister.rs b/rs/tests/driver/src/driver/asset_canister.rs index ea41ffd3188..a343b74d2e3 100644 --- a/rs/tests/driver/src/driver/asset_canister.rs +++ b/rs/tests/driver/src/driver/asset_canister.rs @@ -16,7 +16,9 @@ use tokio::task; #[async_trait] pub trait DeployAssetCanister { - async fn deploy_asset_canister(&self) -> Result; + async fn deploy_legacy_asset_canister(&self) -> Result; + async fn deploy_long_asset_canister(&self) -> Result; + async fn deploy_asset_canister(&self, wasm_env_var_name: &str) -> Result; } #[async_trait] @@ -24,17 +26,25 @@ impl DeployAssetCanister for T where T: HasTestEnv + Send + Sync, { - async fn deploy_asset_canister(&self) -> Result { + async fn deploy_legacy_asset_canister(&self) -> Result { + self.deploy_asset_canister("ASSET_CANISTER_WASM_PATH").await + } + async fn deploy_long_asset_canister(&self) -> Result { + self.deploy_asset_canister("LONG_ASSET_CANISTER_WASM_PATH") + .await + } + async fn deploy_asset_canister(&self, wasm_env_var_name: &str) -> Result { let env = self.test_env(); let logger = env.logger(); let app_node = env.get_first_healthy_application_node_snapshot(); let canister_id = task::spawn_blocking({ let app_node = app_node.clone(); + let wasm_env_var_name = wasm_env_var_name.to_string(); move || { app_node.create_and_install_canister_with_arg( - &env::var("ASSET_CANISTER_WASM_PATH") - .expect("ASSET_CANISTER_WASM_PATH not set"), + &env::var(wasm_env_var_name.clone()) + .unwrap_or_else(|_| panic!("{} not set", wasm_env_var_name)), None, ) } diff --git a/rs/types/types/src/ingress.rs b/rs/types/types/src/ingress.rs index 60ff68a0b63..3985fcd80ab 100644 --- a/rs/types/types/src/ingress.rs +++ b/rs/types/types/src/ingress.rs @@ -1,7 +1,7 @@ //! Ingress types. use crate::artifact::IngressMessageId; -use crate::{CanisterId, CountBytes, PrincipalId, Time, UserId}; +use crate::{CanisterId, MemoryDiskBytes, PrincipalId, Time, UserId}; use ic_error_types::{ErrorCode, UserError}; #[cfg(test)] use ic_exhaustive_derive::ExhaustiveSet; @@ -107,7 +107,7 @@ impl IngressStatus { pub fn payload_bytes(&self) -> usize { match self { IngressStatus::Known { state, .. } => match state { - IngressState::Completed(result) => result.count_bytes(), + IngressState::Completed(result) => result.memory_bytes(), IngressState::Failed(error) => error.description().as_bytes().len(), _ => 0, }, @@ -176,13 +176,17 @@ pub enum WasmResult { Reject(String), } -impl CountBytes for WasmResult { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for WasmResult { + fn memory_bytes(&self) -> usize { match self { WasmResult::Reply(bytes) => bytes.len(), WasmResult::Reject(string) => string.as_bytes().len(), } } + + fn disk_bytes(&self) -> usize { + 0 + } } impl WasmResult { diff --git a/rs/types/types/src/lib.rs b/rs/types/types/src/lib.rs index 2f5f8951ac0..aa2f743e5ea 100644 --- a/rs/types/types/src/lib.rs +++ b/rs/types/types/src/lib.rs @@ -529,30 +529,56 @@ pub trait CountBytes { fn count_bytes(&self) -> usize; } -impl CountBytes for Time { - fn count_bytes(&self) -> usize { +/// Allow an object to reprt its own byte size on disk and in memory. Not +/// necessarilly exact. +pub trait MemoryDiskBytes { + fn memory_bytes(&self) -> usize; + fn disk_bytes(&self) -> usize; +} + +impl MemoryDiskBytes for Time { + fn memory_bytes(&self) -> usize { 8 } + + fn disk_bytes(&self) -> usize { + 0 + } } -impl CountBytes for Result { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for Result { + fn memory_bytes(&self) -> usize { + match self { + Ok(result) => result.memory_bytes(), + Err(err) => err.memory_bytes(), + } + } + + fn disk_bytes(&self) -> usize { match self { - Ok(result) => result.count_bytes(), - Err(err) => err.count_bytes(), + Ok(result) => result.disk_bytes(), + Err(err) => err.disk_bytes(), } } } -impl CountBytes for Arc { - fn count_bytes(&self) -> usize { - self.as_ref().count_bytes() +impl MemoryDiskBytes for Arc { + fn memory_bytes(&self) -> usize { + self.as_ref().memory_bytes() + } + + fn disk_bytes(&self) -> usize { + self.as_ref().disk_bytes() } } -// Implementing `CountBytes` in `ic_error_types` introduces a circular dependency. -impl CountBytes for ic_error_types::UserError { - fn count_bytes(&self) -> usize { +// Implementing `MemoryDiskBytes` in `ic_error_types` introduces a circular dependency. +impl MemoryDiskBytes for ic_error_types::UserError { + fn memory_bytes(&self) -> usize { self.count_bytes() } + + fn disk_bytes(&self) -> usize { + 0 + } } diff --git a/rs/types/wasm_types/src/lib.rs b/rs/types/wasm_types/src/lib.rs index 611e3d3431c..91a6390e4ff 100644 --- a/rs/types/wasm_types/src/lib.rs +++ b/rs/types/wasm_types/src/lib.rs @@ -6,7 +6,7 @@ pub use errors::{ doc_ref, AsErrorHelp, ErrorHelp, WasmEngineError, WasmError, WasmInstrumentationError, WasmValidationError, }; -use ic_types::CountBytes; +use ic_types::MemoryDiskBytes; use ic_utils::byte_slice_fmt::truncate_and_format; use ic_validate_eq::ValidateEq; use ic_validate_eq_derive::ValidateEq; @@ -174,10 +174,14 @@ impl TryFrom> for WasmHash { } } -impl CountBytes for WasmHash { - fn count_bytes(&self) -> usize { +impl MemoryDiskBytes for WasmHash { + fn memory_bytes(&self) -> usize { self.0.len() } + + fn disk_bytes(&self) -> usize { + 0 + } } impl std::fmt::Display for WasmHash { diff --git a/rs/utils/lru_cache/BUILD.bazel b/rs/utils/lru_cache/BUILD.bazel index a148d9cb8fd..7b07074ae14 100644 --- a/rs/utils/lru_cache/BUILD.bazel +++ b/rs/utils/lru_cache/BUILD.bazel @@ -17,7 +17,9 @@ rust_library( rust_test( name = "lru_cache_test", crate = ":lru_cache", - deps = [], + deps = [ + "@crate_index//:proptest", + ], ) rust_doc_test( diff --git a/rs/utils/lru_cache/Cargo.toml b/rs/utils/lru_cache/Cargo.toml index f6218e6897c..cdf5ebe48b5 100644 --- a/rs/utils/lru_cache/Cargo.toml +++ b/rs/utils/lru_cache/Cargo.toml @@ -11,3 +11,6 @@ documentation.workspace = true [dependencies] ic-types = { path = "../../types/types" } lru = { version = "0.7.8", default-features = false } + +[dev-dependencies] +proptest = { workspace = true } diff --git a/rs/utils/lru_cache/src/lib.rs b/rs/utils/lru_cache/src/lib.rs index c181fd32343..e6a5a14ea53 100644 --- a/rs/utils/lru_cache/src/lib.rs +++ b/rs/utils/lru_cache/src/lib.rs @@ -1,4 +1,4 @@ -use ic_types::{CountBytes, NumBytes}; +use ic_types::{MemoryDiskBytes, NumBytes}; use std::hash::Hash; /// The upper bound on cache item size and cache capacity. @@ -11,38 +11,48 @@ const MAX_SIZE: usize = usize::MAX / 2; /// sizes of the cached items does not exceed the pre-configured capacity. pub struct LruCache where - K: CountBytes + Eq + Hash, - V: CountBytes, + K: MemoryDiskBytes + Eq + Hash, + V: MemoryDiskBytes, { cache: lru::LruCache, - capacity: usize, - size: usize, + memory_capacity: usize, + disk_capacity: usize, + memory_size: usize, + disk_size: usize, } -impl CountBytes for LruCache +impl MemoryDiskBytes for LruCache where - K: CountBytes + Eq + Hash, - V: CountBytes, + K: MemoryDiskBytes + Eq + Hash, + V: MemoryDiskBytes, { - fn count_bytes(&self) -> usize { - self.size + fn memory_bytes(&self) -> usize { + self.memory_size + } + + fn disk_bytes(&self) -> usize { + self.disk_size } } impl LruCache where - K: CountBytes + Eq + Hash, - V: CountBytes, + K: MemoryDiskBytes + Eq + Hash, + V: MemoryDiskBytes, { - /// Constructs a new LRU cache with the given capacity. - /// The capacity must not exceed `MAX_SIZE = (2^63 - 1)`. - pub fn new(capacity: NumBytes) -> Self { - let capacity = capacity.get() as usize; - assert!(capacity <= MAX_SIZE); + /// Constructs a new LRU cache with the given memory and disk capacity. The + /// capacities must not exceed `MAX_SIZE = (2^63 - 1)`. + pub fn new(memory_capacity: NumBytes, disk_capacity: NumBytes) -> Self { + let memory_capacity = memory_capacity.get() as usize; + let disk_capacity = disk_capacity.get() as usize; + assert!(memory_capacity <= MAX_SIZE); + assert!(disk_capacity <= MAX_SIZE); let lru_cache = Self { cache: lru::LruCache::unbounded(), - capacity, - size: 0, + memory_capacity, + disk_capacity, + memory_size: 0, + disk_size: 0, }; lru_cache.check_invariants(); lru_cache @@ -50,7 +60,10 @@ where /// Creates a new LRU Cache that never automatically evicts items. pub fn unbounded() -> Self { - Self::new(NumBytes::new(MAX_SIZE as u64)) + Self::new( + NumBytes::new(MAX_SIZE as u64), + NumBytes::new(MAX_SIZE as u64), + ) } /// Returns the value corresponding to the given key. @@ -63,21 +76,31 @@ where /// the cache or other cache entries are evicted (due to the cache capacity), /// then it returns the old entry's key-value pairs. Otherwise, returns an empty vector. pub fn push(&mut self, key: K, value: V) -> Vec<(K, V)> { - let size = key.count_bytes() + value.count_bytes(); - assert!(size <= MAX_SIZE); + let memory_size = key.memory_bytes() + value.memory_bytes(); + assert!(memory_size <= MAX_SIZE); + let disk_size = key.disk_bytes() + value.disk_bytes(); + assert!(disk_size <= MAX_SIZE); let removed_entry = self.cache.push(key, value); if let Some((removed_key, removed_value)) = &removed_entry { - let removed_size = removed_key.count_bytes() + removed_value.count_bytes(); - debug_assert!(self.size >= removed_size); - // This cannot underflow because we know that `self.size` is + let memory_removed_size = removed_key.memory_bytes() + removed_value.memory_bytes(); + debug_assert!(self.memory_size >= memory_removed_size); + // This cannot underflow because we know that `self.memory_size` is // the sum of sizes of all items in the cache. - self.size -= removed_size; + self.memory_size -= memory_removed_size; + + let disk_removed_size = removed_key.disk_bytes() + removed_value.disk_bytes(); + debug_assert!(self.disk_size >= disk_removed_size); + // This cannot underflow because we know that `self.disk_size` is + // the sum of sizes of all items in the cache. + self.disk_size -= disk_removed_size; } // This cannot overflow because we know that - // `self.size <= self.capacity <= MAX_SIZE` - // and `size <= MAX_SIZE == usize::MAX / 2`. - self.size += size; + // `self.memory_size <= self.memory_capacity <= MAX_SIZE` + // and `memory_size <= MAX_SIZE == usize::MAX / 2`. + self.memory_size += memory_size; + // Similar as for `memory_size``. + self.disk_size += disk_size; let mut evicted_entries = self.evict(); self.check_invariants(); @@ -89,9 +112,14 @@ where /// `None` if it does not exist. pub fn pop(&mut self, key: &K) -> Option { if let Some((key, value)) = self.cache.pop_entry(key) { - let size = key.count_bytes() + value.count_bytes(); - debug_assert!(self.size >= size); - self.size -= size; + let memory_size = key.memory_bytes() + value.memory_bytes(); + debug_assert!(self.memory_size >= memory_size); + self.memory_size -= memory_size; + + let disk_size = key.disk_bytes() + value.disk_bytes(); + debug_assert!(self.disk_size >= disk_size); + self.disk_size -= disk_size; + self.check_invariants(); Some(value) } else { @@ -102,7 +130,8 @@ where /// Clears the cache by removing all items. pub fn clear(&mut self) { self.cache.clear(); - self.size = 0; + self.memory_size = 0; + self.disk_size = 0; self.check_invariants(); } @@ -120,14 +149,20 @@ where /// Returns the vector of evicted key-value pairs. fn evict(&mut self) -> Vec<(K, V)> { let mut ret = vec![]; - while self.size > self.capacity { + while self.memory_size > self.memory_capacity || self.disk_size > self.disk_capacity { match self.cache.pop_lru() { Some((key, value)) => { - let size = key.count_bytes() + value.count_bytes(); - debug_assert!(self.size >= size); - // This cannot underflow because we know that `self.size` is - // the sum of sizes of all items in the cache. - self.size -= size; + let memory_size = key.memory_bytes() + value.memory_bytes(); + debug_assert!(self.memory_size >= memory_size); + // This cannot underflow because we know that `self.memory_size` is + // the sum of memory sizes of all items in the cache. + self.memory_size = self.memory_size.saturating_sub(memory_size); + + let disk_size = key.disk_bytes() + value.disk_bytes(); + debug_assert!(self.disk_size >= disk_size); + // This cannot underflow because we know that `self.disk_size` is + // the sum of disk sizes of all items in the cache. + self.disk_size = self.disk_size.saturating_sub(disk_size); ret.push((key, value)); } @@ -143,14 +178,22 @@ where #[cfg(debug_assertions)] if self.len() < 1_000 { debug_assert_eq!( - self.size, + self.memory_size, + self.cache + .iter() + .map(|(key, value)| key.memory_bytes() + value.memory_bytes()) + .sum::() + ); + debug_assert_eq!( + self.disk_size, self.cache .iter() - .map(|(key, value)| key.count_bytes() + value.count_bytes()) + .map(|(key, value)| key.disk_bytes() + value.disk_bytes()) .sum::() ); } - debug_assert!(self.size <= self.capacity); + debug_assert!(self.memory_size <= self.memory_capacity); + debug_assert!(self.disk_size <= self.disk_capacity); } } @@ -161,24 +204,45 @@ mod tests { #[derive(Eq, PartialEq, Hash, Debug)] struct ValueSize(u32, usize); - impl CountBytes for ValueSize { - fn count_bytes(&self) -> usize { + impl MemoryDiskBytes for ValueSize { + fn memory_bytes(&self) -> usize { + self.1 + } + + fn disk_bytes(&self) -> usize { + 0 + } + } + + #[derive(Eq, PartialEq, Hash, Debug)] + struct MemoryDiskValue(u32, usize, usize); + + impl MemoryDiskBytes for MemoryDiskValue { + fn memory_bytes(&self) -> usize { self.1 } + + fn disk_bytes(&self) -> usize { + self.2 + } } #[derive(Eq, PartialEq, Hash, Debug)] struct Key(u32); - impl CountBytes for Key { - fn count_bytes(&self) -> usize { + impl MemoryDiskBytes for Key { + fn memory_bytes(&self) -> usize { + 0 + } + + fn disk_bytes(&self) -> usize { 0 } } #[test] fn lru_cache_single_entry() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); assert!(lru.get(&Key(0)).is_none()); @@ -201,7 +265,7 @@ mod tests { #[test] fn lru_cache_multiple_entries() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); for i in 0..20 { lru.push(Key(i), ValueSize(i, 1)); @@ -219,7 +283,7 @@ mod tests { #[test] fn lru_cache_value_eviction() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); assert!(lru.get(&Key(0)).is_none()); @@ -269,7 +333,7 @@ mod tests { #[test] fn lru_cache_key_eviction() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); assert!(lru.get(&ValueSize(0, 10)).is_none()); @@ -325,7 +389,7 @@ mod tests { #[test] fn lru_cache_key_and_value_eviction() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); let evicted = lru.push(ValueSize(0, 5), ValueSize(42, 5)); assert_eq!(*lru.get(&ValueSize(0, 5)).unwrap(), ValueSize(42, 5)); @@ -359,7 +423,7 @@ mod tests { #[test] fn lru_cache_clear() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); lru.push(Key(0), ValueSize(0, 10)); lru.clear(); assert!(lru.get(&Key(0)).is_none()); @@ -367,7 +431,7 @@ mod tests { #[test] fn lru_cache_pop() { - let mut lru = LruCache::::new(NumBytes::new(10)); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(0)); lru.push(Key(0), ValueSize(0, 5)); lru.push(Key(1), ValueSize(1, 5)); lru.pop(&Key(0)); @@ -379,25 +443,160 @@ mod tests { #[test] fn lru_cache_count_bytes_and_len() { - let mut lru = LruCache::::new(NumBytes::new(10)); - assert_eq!(0, lru.count_bytes()); + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(20)); + assert_eq!(0, lru.memory_bytes()); + assert_eq!(0, lru.disk_bytes()); assert_eq!(0, lru.len()); assert!(lru.is_empty()); - lru.push(Key(0), ValueSize(0, 4)); - assert_eq!(4, lru.count_bytes()); + lru.push(Key(0), MemoryDiskValue(0, 4, 10)); + assert_eq!(4, lru.memory_bytes()); + assert_eq!(10, lru.disk_bytes()); assert_eq!(1, lru.len()); assert!(!lru.is_empty()); - lru.push(Key(1), ValueSize(1, 6)); - assert_eq!(10, lru.count_bytes()); + lru.push(Key(1), MemoryDiskValue(1, 6, 2)); + assert_eq!(10, lru.memory_bytes()); + assert_eq!(12, lru.disk_bytes()); assert_eq!(2, lru.len()); assert!(!lru.is_empty()); lru.pop(&Key(0)); - assert_eq!(6, lru.count_bytes()); + assert_eq!(6, lru.memory_bytes()); + assert_eq!(2, lru.disk_bytes()); assert_eq!(1, lru.len()); assert!(!lru.is_empty()); lru.pop(&Key(1)); - assert_eq!(0, lru.count_bytes()); + assert_eq!(0, lru.memory_bytes()); + assert_eq!(0, lru.disk_bytes()); assert_eq!(0, lru.len()); assert!(lru.is_empty()); } + + #[test] + fn lru_cache_disk_and_memory_single_entry() { + let mut lru = LruCache::::new(NumBytes::new(10), NumBytes::new(20)); + + assert!(lru.get(&Key(0)).is_none()); + + // Can't insert a value if memory or disk is too large. + let evicted = lru.push(Key(0), MemoryDiskValue(42, 11, 0)); + assert_eq!(lru.get(&Key(0)), None); + assert_eq!(evicted, vec![(Key(0), MemoryDiskValue(42, 11, 0))]); + + let evicted = lru.push(Key(0), MemoryDiskValue(42, 0, 21)); + assert_eq!(lru.get(&Key(0)), None); + assert_eq!(evicted, vec![(Key(0), MemoryDiskValue(42, 0, 21))]); + + // Can insert if both sizes fit. + let evicted = lru.push(Key(0), MemoryDiskValue(42, 10, 20)); + assert_eq!(*lru.get(&Key(0)).unwrap(), MemoryDiskValue(42, 10, 20)); + assert_eq!(evicted, vec![]); + + // Inserting a new value removes the old one if memory or disk is + // non-zero (since both are at capacity). + let evicted = lru.push(Key(1), MemoryDiskValue(42, 1, 0)); + assert_eq!(*lru.get(&Key(1)).unwrap(), MemoryDiskValue(42, 1, 0)); + assert_eq!(evicted, vec![(Key(0), MemoryDiskValue(42, 10, 20))]); + + lru.clear(); + let _ = lru.push(Key(0), MemoryDiskValue(42, 10, 20)); + let evicted = lru.push(Key(1), MemoryDiskValue(42, 0, 1)); + assert_eq!(*lru.get(&Key(1)).unwrap(), MemoryDiskValue(42, 0, 1)); + assert_eq!(evicted, vec![(Key(0), MemoryDiskValue(42, 10, 20))]); + } + + #[test] + fn lru_cache_key_and_value_eviction_mixing_memory_and_disk() { + let mut lru = + LruCache::::new(NumBytes::new(10), NumBytes::new(10)); + + let evicted = lru.push(MemoryDiskValue(0, 5, 1), MemoryDiskValue(42, 5, 1)); + assert_eq!( + *lru.get(&MemoryDiskValue(0, 5, 1)).unwrap(), + MemoryDiskValue(42, 5, 1) + ); + assert_eq!(evicted, vec![]); + + let evicted = lru.push(MemoryDiskValue(1, 0, 0), MemoryDiskValue(20, 0, 0)); + assert_eq!( + *lru.get(&MemoryDiskValue(0, 5, 1)).unwrap(), + MemoryDiskValue(42, 5, 1) + ); + assert_eq!( + *lru.get(&MemoryDiskValue(1, 0, 0)).unwrap(), + MemoryDiskValue(20, 0, 0) + ); + assert_eq!(evicted, vec![]); + + let evicted = lru.push(MemoryDiskValue(2, 5, 1), MemoryDiskValue(10, 5, 1)); + assert!(lru.get(&MemoryDiskValue(0, 5, 1)).is_none()); + assert_eq!( + *lru.get(&MemoryDiskValue(1, 0, 0)).unwrap(), + MemoryDiskValue(20, 0, 0) + ); + assert_eq!( + *lru.get(&MemoryDiskValue(2, 5, 1)).unwrap(), + MemoryDiskValue(10, 5, 1) + ); + // The least recently used is the first entry. + assert_eq!( + evicted, + vec![(MemoryDiskValue(0, 5, 1), MemoryDiskValue(42, 5, 1))] + ); + + let evicted = lru.push(MemoryDiskValue(3, 4, 9), MemoryDiskValue(30, 0, 1)); + assert!(lru.get(&MemoryDiskValue(1, 0, 0)).is_none()); + assert!(lru.get(&MemoryDiskValue(2, 5, 1)).is_none()); + assert_eq!( + *lru.get(&MemoryDiskValue(3, 4, 9)).unwrap(), + MemoryDiskValue(30, 0, 1) + ); + // Now the second and third entries are evicted. + assert_eq!( + evicted, + vec![ + (MemoryDiskValue(1, 0, 0), MemoryDiskValue(20, 0, 0)), + (MemoryDiskValue(2, 5, 1), MemoryDiskValue(10, 5, 1)) + ] + ); + } + + mod proptests { + use super::*; + use proptest::prelude::*; + + fn arb_value() -> impl Strategy { + (0..100_u32, 0..50_usize, 0..50_usize).prop_map(|(a, b, c)| MemoryDiskValue(a, b, c)) + } + + proptest! { + /// Proptest checking that the internal invariants are maintained + /// and that the total space of inserted entries equals the total + /// space of evicted entries plus the space of the cache itself. + #[test] + fn test_invariants(entries in prop::collection::vec((arb_value(), arb_value()), 100)) { + let mut lru = LruCache::::new(NumBytes::new(100), NumBytes::new(100)); + let mut total_memory = 0; + let mut total_disk = 0; + let mut evicted_memory = 0; + let mut evicted_disk = 0; + + fn update(memory: &mut usize, disk: &mut usize, k: &MemoryDiskValue, v: &MemoryDiskValue) { + *memory += k.memory_bytes(); + *memory += v.memory_bytes(); + *disk += k.disk_bytes(); + *disk += v.disk_bytes(); + } + + for (k,v) in entries { + update(&mut total_memory, &mut total_disk, &k, &v); + let evicted = lru.push(k,v); + for (k,v) in evicted { + update(&mut evicted_memory, &mut evicted_disk, &k, &v); + } + + assert_eq!(total_memory, evicted_memory + lru.memory_bytes()); + assert_eq!(total_disk, evicted_disk + lru.disk_bytes()); + } + } + } + } } diff --git a/rs/xnet/payload_builder/src/lib.rs b/rs/xnet/payload_builder/src/lib.rs index c54d937a3e6..bbaf916a747 100644 --- a/rs/xnet/payload_builder/src/lib.rs +++ b/rs/xnet/payload_builder/src/lib.rs @@ -1195,6 +1195,85 @@ pub const POOL_SLICE_BYTE_SIZE_MAX: usize = 4 << 20; /// the payload once we're this close to the payload size limit. pub const SLICE_BYTE_SIZE_MIN: usize = 1 << 10; +/// This struct stores stream indices and byte limit used for refilling +/// stream slices of a subnet in a certified slice pool. +pub struct RefillStreamSliceIndices { + pub witness_begin: StreamIndex, + pub msg_begin: StreamIndex, + pub byte_limit: usize, +} + +/// Computes `RefillStreamSliceIndices` for every subnet whose stream slices should be refilled +/// in the given certified slice pool owned by the given subnet. +pub fn refill_stream_slice_indices( + pool_lock: Arc>, + own_subnet_id: SubnetId, +) -> impl Iterator { + let mut result: BTreeMap = BTreeMap::new(); + + let pool_slice_stats = { + let pool = pool_lock.lock().unwrap(); + + if pool.byte_size() > POOL_BYTE_SIZE_SOFT_CAP { + // Abort if pool is already full. + return result.into_iter(); + } + + pool.peers() + // Skip our own subnet, the loopback stream is routed separately. + .filter(|&&subnet_id| subnet_id != own_subnet_id) + .map(|&subnet_id| (subnet_id, pool.slice_stats(subnet_id))) + .collect::>() + }; + + for (subnet_id, slice_stats) in pool_slice_stats { + let (stream_position, messages_begin, msg_count, byte_size) = match slice_stats { + // Have a cached stream position. + (Some(stream_position), messages_begin, msg_count, byte_size) => { + (stream_position, messages_begin, msg_count, byte_size) + } + + // No cached stream position, no pooling / refill necessary. + (None, _, _, _) => continue, + }; + + let (witness_begin, msg_begin, slice_byte_limit) = match messages_begin { + // Existing pooled stream, pull partial slice and append. + Some(messages_begin) if messages_begin == stream_position.message_index => ( + stream_position.message_index, + stream_position.message_index + (msg_count as u64).into(), + POOL_SLICE_BYTE_SIZE_MAX.saturating_sub(byte_size), + ), + + // No pooled stream, or pooled stream does not begin at cached stream position, pull + // complete slice from cached stream position. + _ => ( + stream_position.message_index, + stream_position.message_index, + POOL_SLICE_BYTE_SIZE_MAX, + ), + }; + + if slice_byte_limit < SLICE_BYTE_SIZE_MIN { + // No more space left in the pool for this slice, bail out. + continue; + } + + result.insert( + subnet_id, + RefillStreamSliceIndices { + witness_begin, + msg_begin, + // XNetEndpoint only counts message bytes, allow some overhead (measuread: 350 + // bytes for certification plus base witness, 2% for large payloads). + byte_limit: (slice_byte_limit.saturating_sub(350)) * 98 / 100, + }, + ); + } + + result.into_iter() +} + /// An async task that refills the slice pool. pub struct PoolRefillTask { /// A pool of slices, filled in the background by an async task. @@ -1235,12 +1314,7 @@ impl PoolRefillTask { runtime_handle.spawn(async move { while let Some(registry_version) = refill_receiver.recv().await { - task.refill_pool( - POOL_BYTE_SIZE_SOFT_CAP, - POOL_SLICE_BYTE_SIZE_MAX, - registry_version, - ) - .await; + task.refill_pool(registry_version).await; } }); @@ -1249,68 +1323,17 @@ impl PoolRefillTask { /// Queries all subnets for new slices and puts / appends them to the pool after /// validation against the given registry version. - async fn refill_pool( - &self, - pool_byte_size_soft_cap: usize, - slice_byte_size_max: usize, - registry_version: RegistryVersion, - ) { - let pool_slice_stats = { - let pool = self.pool.lock().unwrap(); - - if pool.byte_size() > pool_byte_size_soft_cap { - // Abort if pool is already full. - return; - } - - pool.peers() - // Skip our own subnet, the loopback stream is routed separately. - .filter(|&&subnet_id| subnet_id != self.endpoint_resolver.subnet_id) - .map(|&subnet_id| (subnet_id, pool.slice_stats(subnet_id))) - .collect::>() - }; - - for (subnet_id, slice_stats) in pool_slice_stats { - let (stream_position, messages_begin, msg_count, byte_size) = match slice_stats { - // Have a cached stream position. - (Some(stream_position), messages_begin, msg_count, byte_size) => { - (stream_position, messages_begin, msg_count, byte_size) - } - - // No cached stream position, no pooling / refill necessary. - (None, _, _, _) => continue, - }; - - let (witness_begin, msg_begin, slice_byte_limit) = match messages_begin { - // Existing pooled stream, pull partial slice and append. - Some(messages_begin) if messages_begin == stream_position.message_index => ( - stream_position.message_index, - stream_position.message_index + (msg_count as u64).into(), - slice_byte_size_max.saturating_sub(byte_size), - ), - - // No pooled stream, or pooled stream does not begin at cached stream position, pull - // complete slice from cached stream position. - _ => ( - stream_position.message_index, - stream_position.message_index, - slice_byte_size_max, - ), - }; - - if slice_byte_limit < SLICE_BYTE_SIZE_MIN { - // No more space left in the pool for this slice, bail out. - continue; - } + async fn refill_pool(&self, registry_version: RegistryVersion) { + let refill_stream_slice_indices = + refill_stream_slice_indices(self.pool.clone(), self.endpoint_resolver.subnet_id); + for (subnet_id, indices) in refill_stream_slice_indices { // `XNetEndpoint` URL of a node on `subnet_id`. let endpoint_locator = match self.endpoint_resolver.xnet_endpoint_url( subnet_id, - witness_begin, - msg_begin, - // XNetEndpoint only counts message bytes, allow some overhead (measuread: 350 - // bytes for certification plus base witness, 2% for large payloads). - (slice_byte_limit.saturating_sub(350)) * 98 / 100, + indices.witness_begin, + indices.msg_begin, + indices.byte_limit, ) { Ok(endpoint_locator) => endpoint_locator, Err(e) => { @@ -1336,7 +1359,7 @@ impl PoolRefillTask { Ok(slice) => { let logger = log.clone(); let res = tokio::task::spawn_blocking(move || { - if witness_begin != msg_begin { + if indices.witness_begin != indices.msg_begin { // Pulled a stream suffix, append to pooled slice. pool.lock() .unwrap() diff --git a/testnet/tools/nns-tools/add-release-to-changelog.sh b/testnet/tools/nns-tools/add-release-to-changelog.sh index e3ca0d7d033..296d6d841bd 100755 --- a/testnet/tools/nns-tools/add-release-to-changelog.sh +++ b/testnet/tools/nns-tools/add-release-to-changelog.sh @@ -25,7 +25,7 @@ cd "$(repo_root)" PWD="$(pwd)" # Fetch the proposal. -print_purple "Fetching proposal ${PROPOSAL_ID}..." >&2 +print_cyan "⏳ Fetching proposal ${PROPOSAL_ID}..." >&2 PROPOSAL_INFO=$( __dfx --quiet \ canister call \ @@ -38,7 +38,7 @@ PROPOSAL_INFO=$( # Unwrap. LEN=$(echo "${PROPOSAL_INFO}" | jq '. | length') if [[ "${LEN}" -ne 1 ]]; then - print_red "Unexpected result from the get_proposal_info method:" >&2 + print_red "💀 Unexpected result from the get_proposal_info method:" >&2 print_red "Should have one element, but has ${LEN}" >&2 exit 1 fi @@ -47,7 +47,7 @@ PROPOSAL_INFO=$(echo "${PROPOSAL_INFO}" | jq '.[0]') # Assert was executed. EXECUTED_TIMESTAMP_SECONDS=$(echo "${PROPOSAL_INFO}" | jq '.executed_timestamp_seconds | tonumber') if [[ "${EXECUTED_TIMESTAMP_SECONDS}" -eq 0 ]]; then - print_red "Proposal ${PROPOSAL_ID} exists, but was not successfully executed." >&2 + print_red "💀 Proposal ${PROPOSAL_ID} exists, but was not successfully executed." >&2 exit 1 fi SECONDS_AGO=$(($(date +%s) - "${EXECUTED_TIMESTAMP_SECONDS}")) @@ -56,21 +56,36 @@ EXECUTED_ON=$( --date=@"${EXECUTED_TIMESTAMP_SECONDS}" \ --iso-8601 ) -print_purple "Proposal ${PROPOSAL_ID} was executed ${SECONDS_AGO} seconds ago." >&2 +print_cyan "🗳️ Proposal ${PROPOSAL_ID} was executed ${SECONDS_AGO} seconds ago." >&2 # Extract which canister was upgraded, and to what commit. -TITLE=$(echo "${PROPOSAL_INFO}" | jq -r '.proposal[0].summary' | head -n 1) -CANISTER_NAME=$( - echo "${TITLE}" \ - | sed 's/# Upgrade the //' | sed 's/ Canister to Commit .*//' \ - | tr '[:upper:]' '[:lower:]' -) -DESTINATION_COMMIT_ID=$(echo "${TITLE}" | sed 's/# Upgrade the .* Canister to Commit //') +TITLE=$(echo "${PROPOSAL_INFO}" | jq -r '.proposal[0].title[0]') +if grep 'Upgrade the .* Canister to Commit .*' <<<"${TITLE}" &>/dev/null; then + GOVERNANCE_TYPE='NNS' + CANISTER_NAME=$( + echo "${TITLE}" \ + | sed 's/Upgrade the //' | sed 's/ Canister to Commit .*//' \ + | tr '[:upper:]' '[:lower:]' + ) + DESTINATION_COMMIT_ID=$(echo "${TITLE}" | sed 's/Upgrade the .* Canister to Commit //') +elif grep 'Publish SNS .* WASM Built at Commit .*' <<<"${TITLE}" &>/dev/null; then + GOVERNANCE_TYPE='SNS' + CANISTER_NAME=$( + echo "${TITLE}" \ + | sed 's/Publish SNS //' | sed 's/ WASM Built at Commit .*//' \ + | tr '[:upper:]' '[:lower:]' + ) + DESTINATION_COMMIT_ID=$(echo "${TITLE}" | sed 's/Publish SNS .* WASM Built at Commit //') +else + print_red "💀 Unable to parse proposal title: ${TITLE}" >&2 + print_red "(In particular, unable to determine which canister and commit.)" >&2 + exit 1 +fi # Fail if the proposal's commit is not checked out. if [[ $(git rev-parse HEAD) != $DESTINATION_COMMIT_ID* ]]; then echo >&2 - print_red "You currently have $(git rev-parse HEAD)" >&2 + print_red "💀 You currently have $(git rev-parse HEAD)" >&2 print_red "checked out, but this command only supports being run when" >&2 print_red "the proposal's commit (${DESTINATION_COMMIT_ID}) is checked out." >&2 exit 1 @@ -78,7 +93,8 @@ fi # cd to the canister's primary code path. CANISTER_CODE_PATH=$( - get_nns_canister_code_location "${CANISTER_NAME}" \ + get_"$(echo "${GOVERNANCE_TYPE}" | tr '[:upper:]' '[:lower:]')"_canister_code_location \ + "${CANISTER_NAME}" \ | sed "s^${PWD}^.^g" \ | cut -d' ' -f1 ) @@ -87,7 +103,7 @@ cd "${CANISTER_CODE_PATH}" # Assert that there is a CHANGELOG.md file. if [[ ! -e CHANGELOG.md ]]; then echo >&2 - print_red "${CANISTER_NAME} has no CHANGELOG.md file." >&2 + print_red "💀 ${CANISTER_NAME} has no CHANGELOG.md file." >&2 exit 1 fi # TODO: Also verify that unreleased_changelog.md exists. @@ -101,7 +117,7 @@ NEW_FEATURES_AND_FIXES=$( ) if [[ -z "${NEW_FEATURES_AND_FIXES}" ]]; then echo >&2 - print_red "The ${CANISTER_NAME} canister has no information in its unreleased_changelog.md." >&2 + print_red "💀 The ${CANISTER_NAME} canister has no information in its unreleased_changelog.md." >&2 exit 1 fi NEW_ENTRY="# ${EXECUTED_ON}: Proposal ${PROPOSAL_ID} @@ -144,3 +160,8 @@ echo -n "${UNRELEASED_CHANGELOG_INTRODUCTION} ## Security """ \ >unreleased_changelog.md + +echo >&2 +print_green '🎉 Success! Added new entry to CHANGELOG.md.' >&2 +print_cyan '💡 Run `git diff` to see the changes. If you are pleased, commit,' >&2 +print_cyan 'push, request review, and merge them into master, per usual.' >&2 diff --git a/testnet/tools/nns-tools/lib/include.sh b/testnet/tools/nns-tools/lib/include.sh index 3ecb2f7aecc..242fdff03c4 100644 --- a/testnet/tools/nns-tools/lib/include.sh +++ b/testnet/tools/nns-tools/lib/include.sh @@ -24,6 +24,7 @@ source "$LIB_DIR/canisters.sh" source "$LIB_DIR/constants.sh" source "$LIB_DIR/functions.sh" source "$LIB_DIR/installers.sh" +source "$LIB_DIR/nns_neurons.sh" source "$LIB_DIR/proposals.sh" source "$LIB_DIR/sns_upgrades.sh" source "$LIB_DIR/topology.sh" diff --git a/testnet/tools/nns-tools/lib/nns_neurons.sh b/testnet/tools/nns-tools/lib/nns_neurons.sh new file mode 100644 index 00000000000..f73edf268cb --- /dev/null +++ b/testnet/tools/nns-tools/lib/nns_neurons.sh @@ -0,0 +1,32 @@ +##: claim_or_refresh +## Usage: $1 +## Claim or refresh an NNS neuron with a particular ID +## NETWORK: The network to use. +## NEURON_ID: The neuron id to claim or refresh. +## Example: claim_or_refresh ic 1234567890 +nns_claim_or_refresh() { + local network=$1 + local neuron_id=$2 + + local IC=$(repo_root) + local GOV_DID="$IC/rs/nns/governance/canister/governance.did" + + dfx canister \ + --network ic \ + call \ + --candid "$GOV_DID" \ + rrkah-fqaaa-aaaaa-aaaaq-cai \ + manage_neuron "( + record { + id = opt record { id = ${neuron_id}: nat64 }; + command = opt variant { + ClaimOrRefresh = record { + controller = null; + by = opt variant { + NeuronIdOrSubaccount = record { } + } + } + } + } + )" +}