diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..d95cffad9 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,40 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/2.0/configuration-reference +version: 2.1 + +orbs: + slack: circleci/slack@4.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/2.0/configuration-reference/#jobs +jobs: + cargo-test: + # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor + docker: + - image: cimg/rust:1.65.0 + # Add steps to the job + # See: https://circleci.com/docs/2.0/configuration-reference/#steps + steps: + - checkout + - run: + name: "cargo test" + command: | + sudo apt update && sudo apt-get install libfontconfig libfontconfig1-dev libfreetype6-dev; + cargo version; + cargo test --all --all-features; + - slack/notify: + event: fail + template: basic_fail_1 + - slack/notify: + event: pass + template: basic_success_1 + + +# Invoke jobs via workflows +# See: https://circleci.com/docs/2.0/configuration-reference/#workflows +workflows: + build-and-test: + jobs: + - cargo-test: + context: CI-Orchard-slack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e6a6c3ae..8099ff630 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,9 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] steps: + - name: Install dependencies (needed for yeslogic-fontconfig-sys crate) + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install -y libfontconfig1-dev - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable id: toolchain @@ -91,6 +94,9 @@ jobs: name: Intra-doc links runs-on: ubuntu-latest steps: + - name: Install dependencies (needed for yeslogic-fontconfig-sys crate) + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install -y libfontconfig1-dev - uses: actions/checkout@v4 - run: cargo fetch # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. diff --git a/.gitignore b/.gitignore index b4e2dad25..cd4022bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /target **/*.rs.bk .vscode +.idea action-circuit-layout.png +*.[0-9] +*.[0-9][0-9] diff --git a/CHANGELOG.md b/CHANGELOG.md index 995654890..edf7a5608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,16 @@ and this project adheres to Rust's notion of ## [Unreleased] +## [0.8.0] - 2024-03-25 + ### Added - `orchard::note::Rho` - `orchard::action::Action::rho` - `orchard::note_encryption::CompactAction::rho` - `orchard::note_encryption::OrchardDomain::for_compact_action` +- Additions under the `test-dependencies` feature flag: + - `orchard::tree::MerkleHashOrchard::random` + - `impl Distribution for Standard` ### Changed - The following methods have their `Nullifier`-typed argument or return value diff --git a/Cargo.lock b/Cargo.lock index b7c63ea24..3cda52aa9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -40,21 +40,22 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -82,9 +83,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayref" @@ -111,15 +112,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -130,6 +131,18 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bit-set" version = "0.5.3" @@ -159,9 +172,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -186,6 +199,15 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bls12_381" version = "0.8.0" @@ -208,21 +230,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cast" @@ -241,12 +263,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" [[package]] name = "cfg-if" @@ -280,9 +299,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.30" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -294,9 +313,9 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -305,18 +324,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half 1.8.2", + "half", ] [[package]] @@ -338,7 +357,7 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "bitflags 1.3.2", "clap_lex", - "indexmap", + "indexmap 1.9.3", "textwrap", ] @@ -351,15 +370,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "color_quant" version = "1.1.0" @@ -367,10 +377,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "const-cstr" -version = "0.3.0" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" @@ -380,9 +390,9 @@ checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -390,15 +400,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" -version = "0.22.3" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -409,9 +419,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -420,9 +430,9 @@ dependencies = [ [[package]] name = "core-text" -version = "19.2.0" +version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ "core-foundation", "core-graphics", @@ -441,18 +451,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -495,46 +505,37 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -542,6 +543,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -552,6 +565,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "darling" version = "0.10.2" @@ -594,7 +617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.0", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -609,6 +632,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "derive_builder" version = "0.9.0" @@ -634,6 +667,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -676,42 +721,70 @@ dependencies = [ "wio", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] -name = "errno" -version = "0.3.3" +name = "elliptic-curve" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", + "windows-sys", ] [[package]] name = "exr" -version = "1.7.0" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" dependencies = [ "bit_field", "flume", - "half 2.2.1", + "half", "lebe", "miniz_oxide", "rayon-core", @@ -721,15 +794,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -759,9 +832,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -769,21 +842,17 @@ dependencies = [ [[package]] name = "float-ord" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin 0.9.8", + "spin", ] [[package]] @@ -794,11 +863,11 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "font-kit" -version = "0.11.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21fe28504d371085fae9ac7a3450f0b289ab71e07c8e57baa3fb68b9e57d6ce5" +checksum = "2845a73bbd781e691ab7c2a028c579727cd254942e8ced57ff73e0eafd60de87" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "byteorder", "core-foundation", "core-graphics", @@ -806,7 +875,7 @@ dependencies = [ "dirs-next", "dwrote", "float-ord", - "freetype", + "freetype-sys", "lazy_static", "libc", "log", @@ -819,18 +888,30 @@ dependencies = [ [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ + "foreign-types-macros", "foreign-types-shared", ] +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "foreign-types-shared" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "fpe" @@ -846,23 +927,13 @@ dependencies = [ "num-traits", ] -[[package]] -name = "freetype" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" -dependencies = [ - "freetype-sys", - "libc", -] - [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -873,18 +944,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - [[package]] name = "generic-array" version = "0.14.7" @@ -893,26 +952,25 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] name = "gif" -version = "0.11.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ "color_quant", "weezl", @@ -920,9 +978,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" dependencies = [ "color_quant", "weezl", @@ -930,9 +988,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "group" @@ -946,12 +1004,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - [[package]] name = "half" version = "2.2.1" @@ -964,8 +1016,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126a150072b0c38c7b573fe3eaf0af944a7fed09e154071bf2436d3f016f7230" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "arrayvec", "bitvec", @@ -989,8 +1040,7 @@ checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" [[package]] name = "halo2_proofs" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b867a8d9bbb85fca76fff60652b5cd19b853a1c4d0665cb89bee68b18d2caf0" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "blake2b_simd", "ff", @@ -1012,9 +1062,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -1027,9 +1077,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1037,18 +1087,27 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1068,31 +1127,32 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "image" -version = "0.24.4" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8e4fb07cf672b1642304e731ef8a6a4c7891d67bb4fd4f5ce58cd6ed86803c" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", "exr", - "gif 0.11.4", + "gif 0.13.1", "jpeg-decoder", - "num-rational", "num-traits", "png", - "scoped_threadpool", + "qoi", "tiff", ] [[package]] name = "incrementalmerkletree" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361c467824d4d9d4f284be4b2608800839419dccc4d4608f28345237fe354623" +checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" dependencies = [ "either", "proptest", + "rand", + "rand_core", ] [[package]] @@ -1105,22 +1165,31 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + [[package]] name = "inferno" -version = "0.11.14" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e66fa9bb3c52f40d05c11b78919ff2f18993c2305bd8a62556d20cb3e9606f" +checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "atty", "crossbeam-channel", "crossbeam-utils", "dashmap", - "indexmap", + "indexmap 2.2.6", + "is-terminal", "itoa", "log", "num-format", - "num_cpus", "once_cell", "quick-xml", "rgb", @@ -1136,6 +1205,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1147,24 +1227,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jpeg-decoder" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" dependencies = [ "rayon", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1183,13 +1263,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -1200,37 +1294,47 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-sys", + "windows-targets", ] [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1238,9 +1342,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "maybe-rayon" @@ -1254,9 +1358,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1267,15 +1371,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "memuse" version = "0.2.1" @@ -1287,23 +1382,14 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "nix" version = "0.26.4" @@ -1323,11 +1409,10 @@ checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -1344,59 +1429,37 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - [[package]] name = "object" -version = "0.32.1" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -1406,15 +1469,16 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" -version = "0.7.1" +version = "0.8.0" dependencies = [ "aes", + "ahash", "bitvec", "blake2b_simd", "bridgetree", @@ -1422,12 +1486,14 @@ dependencies = [ "ff", "fpe", "group", + "half", "halo2_gadgets", "halo2_proofs", "hex", "image", "incrementalmerkletree", "inferno", + "k256", "lazy_static", "memuse", "nonempty", @@ -1447,15 +1513,15 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1463,13 +1529,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", "windows-targets", ] @@ -1501,61 +1567,40 @@ dependencies = [ [[package]] name = "pathfinder_simd" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" +checksum = "ebf45976c56919841273f2a0fc684c28437e2f304e264557d9c72be5d5a718be" dependencies = [ "rustc_version", ] [[package]] -name = "pest" -version = "2.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pin-project" -version = "1.1.3" +name = "pin-project-lite" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] -name = "pin-project-internal" -version = "1.1.3" +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", + "der", + "spki", ] -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "chrono", "font-kit", @@ -1573,15 +1618,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-bitmap" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cebbe1f70205299abc69e8b295035bb52a6a70ee35474ad10011f0a4efb8543" +checksum = "f7e7f6fb8302456d7c264a94dada86f76d76e1a03e2294ee86ca7da92983b0a6" dependencies = [ "gif 0.12.0", "image", @@ -1590,18 +1635,18 @@ dependencies = [ [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1651,33 +1696,42 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax", "rusty-fork", "tempfile", "unarray", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1695,9 +1749,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1749,9 +1803,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1759,14 +1813,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1789,99 +1841,94 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.7.5", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] -name = "regex-syntax" -version = "0.7.5" +name = "rfc6979" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741" dependencies = [ "bytemuck", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.11" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1902,9 +1949,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1915,12 +1962,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" version = "1.2.0" @@ -1928,54 +1969,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "semver" -version = "0.11.0" +name = "sec1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "semver-parser", + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", ] [[package]] -name = "semver-parser" -version = "0.10.2" +name = "semver" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1984,15 +2048,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "spin" -version = "0.5.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" @@ -2003,6 +2061,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2029,9 +2097,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" @@ -2069,9 +2137,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.31" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -2097,48 +2165,47 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", "rustix", "windows-sys", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", ] [[package]] name = "tiff" -version = "0.7.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f71e422515e83e3ab8a03d4781d05ebf864fc61f4546e6ecffa58cbd34181a0" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -2157,11 +2224,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2169,41 +2235,35 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "ttf-parser" -version = "0.17.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -2225,9 +2285,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "universal-hash" @@ -2241,9 +2301,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.4.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" [[package]] name = "version_check" @@ -2262,9 +2322,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2278,9 +2338,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2288,24 +2348,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2313,28 +2373,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2342,9 +2402,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" @@ -2364,11 +2424,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -2378,32 +2438,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -2412,45 +2473,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "wio" @@ -2472,11 +2539,11 @@ dependencies = [ [[package]] name = "yeslogic-fontconfig-sys" -version = "3.2.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386" +checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" dependencies = [ - "const-cstr", + "cstr", "dlib", "once_cell", "pkg-config", @@ -2485,8 +2552,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4580cd6cee12e44421dac43169be8d23791650816bdb34e6ddfa70ac89c1c5" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#76745f00551d4442dee11ad64a8400b75132d18f" dependencies = [ "chacha20", "chacha20poly1305", @@ -2504,11 +2570,31 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "zeroize" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -2521,14 +2607,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.68", ] [[package]] name = "zip32" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d724a63be4dfb50b7f3617e542984e22e4b4a5b8ca5de91f55613152885e6b22" +checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" dependencies = [ "blake2b_simd", "memuse", diff --git a/Cargo.toml b/Cargo.toml index 48074dd81..ade4c8274 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orchard" -version = "0.7.1" +version = "0.8.0" authors = [ "Sean Bowe ", "Jack Grigg ", @@ -26,12 +26,14 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] aes = "0.8" bitvec = "1" blake2b_simd = "1" +half = "=2.2.1" # Last version requires Rust 1.70 ff = "0.13" fpe = "0.6" group = { version = "0.13", features = ["wnaf-memuse"] } -halo2_gadgets = "0.3" -halo2_proofs = { version = "0.3", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } +halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } hex = "0.4" +k256 = { version = "0.13.0", features = ["arithmetic", "schnorr"] } lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } pasta_curves = "0.5" @@ -41,7 +43,7 @@ reddsa = "0.5" nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" -zcash_note_encryption = "0.4" +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } incrementalmerkletree = "0.5" zcash_spec = "0.1" zip32 = "0.1" @@ -56,14 +58,15 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] bridgetree = "0.4" criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 -halo2_gadgets = { version = "0.3", features = ["test-dependencies"] } -hex = "0.4" +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } proptest = "1.0.0" -zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } +ahash = "=0.8.6" #Pinned: 0.8.7 depends on Rust 1.72 [target.'cfg(unix)'.dev-dependencies] inferno = { version = "0.11", default-features = false, features = ["multithreaded", "nameattr"] } +#clap = "=4.2.0" #Pinned: Used by inferno. Later version requires Rust 1.70 pprof = { version = "0.11", features = ["criterion", "flamegraph"] } [lib] diff --git a/README.md b/README.md index c2138a11f..8e610ad66 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) # +# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) [![CI checks](https://github.com/QED-it/orchard/actions/workflows/ci.yml/badge.svg?branch=zsa1)](https://github.com/QED-it/orchard/actions/workflows/ci.yml) +# Requires Rust 1.65+. diff --git a/benches/circuit.rs b/benches/circuit.rs index 5d66f1421..029f80b55 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -10,28 +10,43 @@ use orchard::{ builder::{Builder, BundleType}, circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; use rand::rngs::OsRng; -fn criterion_benchmark(c: &mut Criterion) { +mod utils; + +use utils::OrchardFlavorBench; + +fn criterion_benchmark(c: &mut Criterion) { let rng = OsRng; let sk = SpendingKey::from_bytes([7; 32]).unwrap(); let recipient = FullViewingKey::from(&sk).address_at(0u32, Scope::External); - let vk = VerifyingKey::build(); - let pk = ProvingKey::build(); + let vk = VerifyingKey::build::(); + let pk = ProvingKey::build::(); let create_bundle = |num_recipients| { - let mut builder = Builder::new(BundleType::DEFAULT, Anchor::from_bytes([0; 32]).unwrap()); + let mut builder = Builder::new( + BundleType::DEFAULT_VANILLA, + Anchor::from_bytes([0; 32]).unwrap(), + ); for _ in 0..num_recipients { builder - .add_output(None, recipient, NoteValue::from_raw(10), None) + .add_output( + None, + recipient, + NoteValue::from_raw(10), + AssetBase::native(), + None, + ) .unwrap(); } - let bundle: Bundle<_, i64> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().0; let instances: Vec<_> = bundle .actions() @@ -45,7 +60,7 @@ fn criterion_benchmark(c: &mut Criterion) { let recipients_range = 1..=4; { - let mut group = c.benchmark_group("proving"); + let mut group = FL::benchmark_group(c, "proving"); group.sample_size(10); for num_recipients in recipients_range.clone() { let (bundle, instances) = create_bundle(num_recipients); @@ -61,7 +76,7 @@ fn criterion_benchmark(c: &mut Criterion) { } { - let mut group = c.benchmark_group("verifying"); + let mut group = FL::benchmark_group(c, "verifying"); for num_recipients in recipients_range { let (bundle, instances) = create_bundle(num_recipients); let bundle = bundle @@ -78,15 +93,25 @@ fn criterion_benchmark(c: &mut Criterion) { } #[cfg(unix)] -criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = criterion_benchmark +fn create_config() -> Criterion { + Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))) } + #[cfg(windows)] +fn create_config() -> Criterion { + Criterion::default() +} + criterion_group! { - name = benches; - config = Criterion::default(); - targets = criterion_benchmark + name = benches_vanilla; + config = create_config(); + targets = criterion_benchmark:: } -criterion_main!(benches); + +criterion_group! { + name = benches_zsa; + config = create_config(); + targets = criterion_benchmark:: +} + +criterion_main!(benches_vanilla, benches_zsa); diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 2cd177e80..5bf072c50 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -2,20 +2,26 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use orchard::{ builder::{Builder, BundleType}, circuit::ProvingKey, + domain::{CompactAction, OrchardDomain}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, - note_encryption::{CompactAction, OrchardDomain}, + note::AssetBase, + orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; use rand::rngs::OsRng; -use zcash_note_encryption::{batch, try_compact_note_decryption, try_note_decryption}; +use zcash_note_encryption_zsa::{batch, try_compact_note_decryption, try_note_decryption}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; -fn bench_note_decryption(c: &mut Criterion) { +mod utils; + +use utils::OrchardFlavorBench; + +fn bench_note_decryption(c: &mut Criterion) { let rng = OsRng; - let pk = ProvingKey::build(); + let pk = ProvingKey::build::(); let fvk = FullViewingKey::from(&SpendingKey::from_bytes([7; 32]).unwrap()); let valid_ivk = fvk.to_ivk(Scope::External); @@ -44,16 +50,31 @@ fn bench_note_decryption(c: &mut Criterion) { .collect(); let bundle = { - let mut builder = Builder::new(BundleType::DEFAULT, Anchor::from_bytes([0; 32]).unwrap()); + let mut builder = Builder::new( + BundleType::DEFAULT_VANILLA, + Anchor::from_bytes([0; 32]).unwrap(), + ); // The builder pads to two actions, and shuffles their order. Add two recipients // so the first action is always decryptable. builder - .add_output(None, recipient, NoteValue::from_raw(10), None) + .add_output( + None, + recipient, + NoteValue::from_raw(10), + AssetBase::native(), + None, + ) .unwrap(); builder - .add_output(None, recipient, NoteValue::from_raw(10), None) + .add_output( + None, + recipient, + NoteValue::from_raw(10), + AssetBase::native(), + None, + ) .unwrap(); - let bundle: Bundle<_, i64> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().0; bundle .create_proof(&pk, rng) .unwrap() @@ -65,7 +86,7 @@ fn bench_note_decryption(c: &mut Criterion) { let domain = OrchardDomain::for_action(action); let compact = { - let mut group = c.benchmark_group("note-decryption"); + let mut group = FL::benchmark_group(c, "note-decryption"); group.throughput(Throughput::Elements(1)); group.bench_function("valid", |b| { @@ -87,7 +108,7 @@ fn bench_note_decryption(c: &mut Criterion) { }; { - let mut group = c.benchmark_group("compact-note-decryption"); + let mut group = FL::benchmark_group(c, "compact-note-decryption"); group.throughput(Throughput::Elements(invalid_ivks.len() as u64)); group.bench_function("invalid", |b| { b.iter(|| { @@ -114,7 +135,7 @@ fn bench_note_decryption(c: &mut Criterion) { }) .collect(); - let mut group = c.benchmark_group("batch-note-decryption"); + let mut group = FL::benchmark_group(c, "batch-note-decryption"); for size in [10, 50, 100] { group.throughput(Throughput::Elements((ivks * size) as u64)); @@ -141,11 +162,25 @@ fn bench_note_decryption(c: &mut Criterion) { } #[cfg(unix)] +fn create_config() -> Criterion { + Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))) +} + +#[cfg(windows)] +fn create_config() -> Criterion { + Criterion::default() +} + criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = bench_note_decryption + name = benches_vanilla; + config = create_config(); + targets = bench_note_decryption:: } -#[cfg(not(unix))] -criterion_group!(benches, bench_note_decryption); -criterion_main!(benches); + +criterion_group! { + name = benches_zsa; + config = create_config(); + targets = bench_note_decryption:: +} + +criterion_main!(benches_vanilla, benches_zsa); diff --git a/benches/utils.rs b/benches/utils.rs new file mode 100644 index 000000000..d5f639278 --- /dev/null +++ b/benches/utils.rs @@ -0,0 +1,28 @@ +use criterion::{measurement::Measurement, BenchmarkGroup, Criterion}; + +use orchard::orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}; + +pub(crate) trait OrchardFlavorBench: OrchardFlavor { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M>; +} + +impl OrchardFlavorBench for OrchardVanilla { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M> { + c.benchmark_group(format!("[OrchardVanilla] {}", group_name)) + } +} + +impl OrchardFlavorBench for OrchardZSA { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M> { + c.benchmark_group(format!("[OrchardZSA] {}", group_name)) + } +} diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 83ad1b4fd..19a8f77fd 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -18,4 +18,5 @@ - [Circuit](design/circuit.md) - [Gadgets](design/circuit/gadgets.md) - [CommitIvk](design/circuit/commit-ivk.md) - - [NoteCommit](design/circuit/note-commit.md) + - [Orchard NoteCommit](design/circuit/note-commit.md) + - [OrchardZSA NoteCommit](design/circuit/zsa-note-commit.md) diff --git a/book/src/design/actions.md b/book/src/design/actions.md index 5bbcec988..73c81a1af 100644 --- a/book/src/design/actions.md +++ b/book/src/design/actions.md @@ -13,14 +13,44 @@ proof per output note, which greatly improved the performance of generating outp removed any arity-hiding from the proofs (instead having the transaction builder pad transactions to 1-in, 2-out). -For Orchard, we take a combined approach: we define an Orchard transaction as containing a +For Orchard(ZSA), we take a combined approach: we define an Orchard transaction as containing a bundle of actions, where each action is both a spend and an output. This provides the same inherent arity-hiding as multi-JoinSplit Sprout, but using Sapling value commitments to balance the transaction without doubling its size. +## Dummy notes for Orchard + +For Orchard, a transaction is a bundle of actions. Each action is composed of one spend and one output. +This means we have the same amount of "spends" and "outputs" in one transaction. +If we would like to create a transaction with a different number of spends and outputs, +we need to add "dummy" spends or outputs to balance their count. +A dummy spend or output is a note with a value of zero and a random recipient address. +In the ZK proof, when the value of the spent note is zero, +we do not verify that the corresponding spent note commitment is part of the Merkle tree. + +## Split notes for OrchardZSA + +For OrchardZSA, if the number of inputs exceeds the number of outputs, +we use dummy output notes (as in Orchard) to fill all actions. +Conversely, if the number of outputs exceeds the number of inputs, we use split notes to fill the actions. +In OrchardZSA, ensuring that the AssetBase is correctly created is crucial. +For this reason, split notes are used instead of dummy spent notes. +Split notes are essentially duplicates of actual spent notes, +but with the following differences: +- The nullifier is randomized to prevent it from being treated as double-spending. +- Its value is excluded from the transaction's or bundle's value balance. + +Within the ZK proof, we verify that the commitment of each spent note (including split notes) +is part of the Merkle tree. This ensures that the AssetBase is constructed properly, +a note associated with this AssetBase exists within the Merkle tree. + +For further details about split notes, refer to +[ZIP226](https://github.com/zcash/zips/blob/main/zips/zip-0226.rst). + ## Memo fields Each Orchard action has a memo field for its corresponding output, as with Sprout and Sapling. We did at one point consider having a single Orchard memo field per transaction, and/or having a mechanism for enabling multiple recipients to decrypt the same memo, but these were decided against in order to keep the overall design simpler. + diff --git a/book/src/design/circuit/note-commit.md b/book/src/design/circuit/note-commit.md index 57494aacc..66cf6bf8e 100644 --- a/book/src/design/circuit/note-commit.md +++ b/book/src/design/circuit/note-commit.md @@ -1,4 +1,4 @@ -# NoteCommit +# Orchard NoteCommit ## Message decomposition diff --git a/book/src/design/circuit/zsa-note-commit.md b/book/src/design/circuit/zsa-note-commit.md new file mode 100644 index 000000000..64be86046 --- /dev/null +++ b/book/src/design/circuit/zsa-note-commit.md @@ -0,0 +1,359 @@ +# OrchardZSA NoteCommit + +In the OrchardZSA protocol, the $\NoteCommit$ function is defined as follows: +$$ +\begin{align} +&\mathsf{NoteCommit^{OrchardZSA}_{rcm}}( +\DiversifiedTransmitBaseRepr, +\DiversifiedTransmitPublicRepr, +\ItoLEBSP{64}(\mathsf{v}), +\ItoLEBSP{\BaseLength{Orchard}}(\rho), +\ItoLEBSP{\BaseLength{Orchard}}(\psi), +\mathsf{AssetBase}) = \\ +&\;\;\;\;\; +\begin{cases} +\mathsf{h_{ZEC}} + [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) &\text{ if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ +\mathsf{h_{ZSA}} + [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) &\text{otherwise} +\end{cases} +\end{align} +$$ +where +$$ +\begin{align} +\mathsf{h_{ZEC}} =&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:Orchard-NoteCommit-M"}, \\ +&\;\;\;\;\; +\DiversifiedTransmitBaseRepr \bconcat +\DiversifiedTransmitPublicRepr \bconcat +\ItoLEBSP{64}(\mathsf{v}) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\rho) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\psi)) +\end{align} +$$ +and +$$ +\begin{align} +\mathsf{h_{ZSA}} =&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, \\ +&\;\;\;\;\; +\DiversifiedTransmitBaseRepr \bconcat +\DiversifiedTransmitPublicRepr \bconcat +\ItoLEBSP{64}(\mathsf{v}) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\rho) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\psi) \bconcat +\mathsf{AssetBase}) +\end{align} +$$ +where: +- $\DiversifiedTransmitBaseRepr, \DiversifiedTransmitPublicRepr, \mathsf{AssetBase}$ are representations of + Pallas curve points, with $255$ bits used for the $x$-coordinate and $1$ bit used for + the $y$-coordinate. +- $\rho, \psi$ are Pallas base field elements. +- $\mathsf{v}$ is a $64$-bit value. +- $\BaseLength{Orchard} = 255.$ + +We will only present the updates and additions compared to +[Orchard $\NoteCommit$](./note-commit.md). + +## Message decomposition + +Sinsemilla operates on multiples of 10 bits, so we start by decomposing the message into +chunks: + +$$ +\begin{aligned} +\DiversifiedTransmitBaseRepr &= a \bconcat b_0 \bconcat b_1 \bconcat b_2 \\ + &= (\text{bits 0..=249 of } x(\mathsf{g_d})) \bconcat + (\text{bits 250..=253 of } x(\mathsf{g_d})) \bconcat + (\text{bit 254 of } x(\mathsf{g_d})) \bconcat + (ỹ \text{ bit of } \mathsf{g_d}) \\ +\DiversifiedTransmitPublicRepr &= b_3 \bconcat c \bconcat d_0 \bconcat d_1 \\ + &= (\text{bits 0..=3 of } x(\mathsf{pk_d})) \bconcat + (\text{bits 4..=253 of } x(\mathsf{pk_d})) \bconcat + (\text{bit 254 of } x(\mathsf{pk_d})) \bconcat + (ỹ \text{ bit of } \mathsf{pk_d}) \\ +\ItoLEBSP{64}(v) &= d_2 \bconcat d_3 \bconcat e_0 \\ + &= (\text{bits 0..=7 of } v) \bconcat + (\text{bits 8..=57 of } v) \bconcat + (\text{bits 58..=63 of } v) \\ +\ItoLEBSP{\BaseLength{Orchard}}(\rho) &= e_1 \bconcat f \bconcat g_0 \\ + &= (\text{bits 0..=3 of } \rho) \bconcat + (\text{bits 4..=253 of } \rho) \bconcat + (\text{bit 254 of } \rho) \\ +\ItoLEBSP{\BaseLength{Orchard}}(\psi) &= g_1 \bconcat g_2 \bconcat h_0 \bconcat h_1 \\ + &= (\text{bits 0..=8 of } \psi) \bconcat + (\text{bits 9..=248 of } \psi) \bconcat + (\text{bits 249..=253 of } \psi) \bconcat + (\text{bit 254 of } \psi) \\ +\mathsf{AssetBase} &= h_2^{ZSA} \bconcat i \bconcat j_0 \bconcat j_1 \\ + &= (\text{bits 0..=3 of } x(\mathsf{AssetBase})) \bconcat + (\text{bits 4..=253 of } x(\mathsf{AssetBase})) \bconcat + (\text{bit 254 of } x(\mathsf{AssetBase})) \bconcat + (ỹ \text{ bit of } \mathsf{AssetBase}) \\ +\end{aligned} +$$ + +Then we recompose the chunks into message pieces: + +$$ +\begin{array}{|c|l|} +\hline +\text{Length (bits)} & \text{Piece} \\\hline +250 & a \\ + 10 & b = b_0 \bconcat b_1 \bconcat b_2 \bconcat b_3 \\ +250 & c \\ + 60 & d = d_0 \bconcat d_1 \bconcat d_2 \bconcat d_3 \\ + 10 & e = e_0 \bconcat e_1 \\ +250 & f \\ +250 & g = g_0 \bconcat g_1 \bconcat g_2 \\ + 10 & h = h_0 \bconcat h_1 \bconcat h_2^{ZSA} \\ +250 & i \\ + 10 & j_0 \bconcat j_1 \bconcat j_2 \\ + \hline +\end{array} +$$ + +where $j_2$ is 8 zero bits (corresponding to the padding applied by the Sinsemilla +[$\mathsf{pad}$ function](https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash)). + +## Message piece decomposition + +In this section, we will only present the updates and additions compared to +[Message piece decomposition for Orchard](./note-commit.md#message-piece-decomposition). + +As $a$, $c$ and $f$, $i$ is also witnessed and constrained outside the gate. + +### $h$ decomposition + +$$\begin{cases} +h^{ZEC} = h_0 \bconcat h_1 \bconcat 0000 \\ +h^{ZSA} = h_0 \bconcat h_1 \bconcat h_2^{ZSA} +\end{cases}$$ +$h^{ZEC}$ and $h^{ZSA}$ have been constrained to be $10$ bits each by the Sinsemilla hash. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & q_{\NoteCommit,h} \\\hline + h^{ZEC} & h_0 & h_1 & 1 \\\hline + h^{ZSA} & h_2^{ZSA} & & 0 \\\hline +\end{array} +$$ + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline + 3 & q_{\NoteCommit,h} \cdot \BoolCheck{h_1} = 0 \\\hline + 2 & q_{\NoteCommit,h} \cdot (h^{ZEC} - (h_0 + h_1 \cdot 2^5)) = 0 \\\hline + 2 & q_{\NoteCommit,h} \cdot (h^{ZSA} - (h_0 + h_1 \cdot 2^5 + h_2^{ZSA} \cdot 2^6)) = 0 \\\hline +\end{array} +$$ + +Outside this gate, we have constrained: +- $\ShortLookupRangeCheck{h_0, 5}$ +- $\ShortLookupRangeCheck{h_2^{ZSA}, 4}$ + +### $j$ decomposition + +$$j = j_0 \bconcat j_1 \bconcat j_2$$ +with $j_2$ is 8 zero bits. + +$j$ has been constrained to be $10$ bits by the $\SinsemillaHash$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & q_{\NoteCommit,j} \\\hline + j & j_0 & j_1 & 1 \\\hline +\end{array} +$$ + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline + 3 & q_{\NoteCommit,j} \cdot \BoolCheck{j_0} = 0 \\\hline + 3 & q_{\NoteCommit,j} \cdot \BoolCheck{j_1} = 0 \\\hline +2 & q_{\NoteCommit,j} \cdot (j - (j_0 + j_1 \cdot 2)) = 0 \\\hline +\end{array} +$$ + +## Field element checks + +In addition to [field element checks for Orchard NoteCommit](./note-commit.md#field-element-checks), +we have to +- constrain $\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase}))$ + to be 255-bit value, with top bit $j_0$. +- constrain $\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase})) = x(\mathsf{AssetBase}) \pmod{q_\mathbb{P}}$ +where $q_\mathbb{P}$ is the Pallas base field modulus. +- check that $\mathsf{AssetBase}$ is indeed canonically-encoded field elements, i.e. +$$\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase})) < q_\mathbb{P}$$ + +$\mathsf{pk_d}$ and $\mathsf{AssetBase}$ have a similar message piece decomposition. +Thus, we will reuse the $\mathsf{pk_d}$ gates to check those constraints on $\mathsf{AssetBase}$. + +### $x(\mathsf{AssetBase})$ is a Pallas base field element +Recall that $x(\mathsf{AssetBase}) = h_2^{ZSA} + 2^4 \cdot i + 2^{254} \cdot j_0$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & A_9 & q_{\NoteCommit,x(\mathsf{pk_d})} \\\hline +x(\mathsf{AssetBase}) & h_2^{ZSA} & i & z_{i,13} & 1 \\\hline + & j_0 & h_2i' & z_{h_2i',14} & 0 \\\hline +\end{array} +$$ + +where +- $z_{i,13}$ is the index-13 running sum output by $\SinsemillaHash(i)$, +- $h_2i' = h_2^{ZSA} + 2^4 \cdot i + 2^{140} - t_\mathbb{P}$, and +- $z_{h_2i',14}$ is the index-14 running sum output by $\SinsemillaHash(h_2i')$, + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +2 & q_{\NoteCommit,x(\mathsf{AssetBast})} \cdot \left(h_2^{ZSA} + i \cdot 2^4 + j_0 \cdot 2^{254} - x(\mathsf{AssetBase}) \right) = 0 \\\hline +3 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot j_0 \cdot z_{i,13} = 0 \\\hline +2 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot (h_2^{ZSA} + i \cdot 2^4 + 2^{140} - t_\mathbb{P} - {h_2}i') = 0 \\\hline +3 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot j_0 \cdot z_{{h_2}i',14} = 0 \\\hline +\end{array} +$$ + +### Decomposition of $y(\mathsf{AssetBase})$ + +We would like to verify that the following decomposition of $y(\mathsf{AssetBase})$ is correct +$$ +\begin{align} +y &= \textsf{LSB} \bconcat k_0 \bconcat k_1 \bconcat k_2 \bconcat k_3\\ + &= \textsf{LSB} + \bconcat \text{ (bits $1..=9$ of $y$) } + \bconcat \text{ (bits $10..=249$ of $y$) } + \bconcat \text{ (bits $250..=253$ of $y$) } + \bconcat \text{ (bit $254$ of $y$) }, +\end{align} +$$ +where $\textsf{LSB}=j_1$. + +To achieve this, we will use the same gate that is utilized to verify the correctness +of the decompositions of $y(\mathsf{g_d})$ and $y(\mathsf{pk_d})$. + +Let $j = \textsf{LSB} + 2 \cdot k_0 + 2^{10} \cdot k_1$. +We decompose $j$ to be $250$ bits using a strict $25-$word +[ten-bit lookup](../decomposition.md#lookup-decomposition). +The running sum outputs allow us to susbstitute $k_1 = z_{j, 1}.$ + +Recall that $\textsf{LSB} = ỹ(\mathsf{AssetBase})$ was piece input to the +Sinsemilla hash and have already been boolean-constrained. +$k_0$ and $k_2$ are constrained outside this gate to $9$ and $4$ bits respectively. +To constrain the remaining chunks, we use the following constraints: + +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +3 & q_{\NoteCommit,y} \cdot \BoolCheck{k_3} = 0 \\\hline +\end{array} +$$ + +Then, to check that the decomposition was correct: +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +2 & q_{\NoteCommit,y} \cdot \left(j - (\textsf{LSB} + k_0 \cdot 2 + k_1 \cdot 2^{10}) \right) = 0 \\\hline +2 & q_{\NoteCommit,y} \cdot \left(y - (j + k_2 \cdot 2^{250} + k_3 \cdot 2^{254}) \right) = 0 \\\hline +\end{array} +$$ + +### $y(\mathsf{AssetBase})$ is a Pallas base field element +Recall that +$$ +\begin{align} +y &= ỹ \bconcat k_0 \bconcat k_1 \bconcat k_2 \bconcat k_3\\ + &= ỹ + \bconcat \text{ (bits $1..=9$ of $y$) } + \bconcat \text{ (bits $10..=249$ of $y$) } + \bconcat \text{ (bits $250..=253$ of $y$) } + \bconcat \text{ (bit $254$ of $y$) }, +\end{align} +$$ +Let $\begin{cases} +j = \textsf{LSB} + 2 \cdot k_0 + 2^{10} \cdot k_1 \\ +j' = j + 2^{130} - t_\mathbb{P} +\end{cases}$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|c|c|} +\hline +A_5 & A_6 & A_7 & A_8 & A_9 & q_{\NoteCommit,y} \\\hline + y & ỹ & k_0 & k_2 & k_3 & 1 \\\hline + j & k_1 & z_{j,13} & j' & z_{j',13} & 0 \\\hline +\end{array} +$$ +where $z_{j,13}$ (resp. $z_{j', 13}$) is the index-13 running sum output by the $10$-bit lookup +decomposition of $j$ (resp. $j'$). + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot k_2 = 0 \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot z_{j,13} = 0 \\\hline +2 & q_{\NoteCommit,y} \cdot (j + 2^{130} - t_\mathbb{P} - j') = 0 \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot z_{j',13} = 0 \\\hline +\end{array} +$$ + +Outside this gate, we have constrained: +- $\ShortLookupRangeCheck{k_0, 9}$ +- $\ShortLookupRangeCheck{k_2, 4}$ + +## $\mathsf{SinsemillaHashToPoint}$ evaluations +To evaluate our OrchardZSA $\NoteCommit$, we must evalute +$\mathsf{h} = \begin{cases} \mathsf{h_{ZEC}} &\text{ if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ +\mathsf{h_{ZSA}} &\text{ otherwise} \end{cases}$. + +We observe that the messages to hash in $\mathsf{h_{ZEC}}$ and $\mathsf{h_{ZSA}}$ have a similar prefix +$$\begin{cases} +\mathsf{h_{ZEC}} = \mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:Orchard-NoteCommit-M"}, +\mathsf{prefix} \bconcat \mathsf{suffix_{ZEC}}) \\ +\mathsf{h_{ZSA}} = \mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, +\mathsf{prefix} \bconcat \mathsf{suffix_{ZSA}}) +\end{cases}$$ +where +$$\begin{cases} +\mathsf{prefix} = a \bconcat b \bconcat c \bconcat d \bconcat e \bconcat f \bconcat g \\ +\mathsf{suffix_{ZEC}} = h_0 \bconcat h_1 \bconcat 0000 \\ +\mathsf{suffix_{ZSA}} = h_0 \bconcat h_1 \bconcat h_2^{ZSA} \bconcat i \bconcat j +\end{cases}$$ + +We will optimize the circuit by leveraging the fact that their respective messages share +a common prefix. More precisely, the circuit will contain the following steps: +1. Evaluate $Q_{init}$ the initial state of the hash function thanks to a multiplexer gate +$$ \mathcal{Q}_{init} = MUX(\mathcal{Q}_{ZSA}, \mathcal{Q}_{ZEC}, \mathsf{AssetBase} == \mathcal{V}^{\mathsf{Orchard}})$$ +where +$$\begin{cases} +\mathcal{Q}_{ZEC} = \mathcal{Q}(\texttt{"z.cash:Orchard-NoteCommit-M"}) \\ +\mathcal{Q}_{ZSA} = \mathcal{Q}(\texttt{"z.cash:ZSA-NoteCommit-M"}) +\end{cases}$$ +2. Evaluate $\mathsf{h_{common}}$ which is equal to the Sinsemilla hash evaluation from the inital +point $\mathcal{Q}_{init}$ with the message $\mathsf{prefix}$ +$$\mathsf{h_{common}} = \mathsf{SinsemillaHash}(\mathcal{Q}_{init}, \mathsf{prefix})$$ +3. Evaluate $\mathsf{h_{ZSA}}$ and $\mathsf{h_{ZEC}}$ which are equal to the Sinsemilla hash evaluations from the initial point $h_{common}$ with the message $\mathsf{suffix_{ZSA}}$ and $\mathsf{suffix_{ZEC}}$ respectively +$$\begin{cases} +\mathsf{h_{ZEC}} = \mathsf{SinsemillaHash}(\mathsf{h_{common}}, \mathsf{suffix_{ZEC}}) \\ +\mathsf{h_{ZSA}} = \mathsf{SinsemillaHash}(\mathsf{h_{common}}, \mathsf{suffix_{ZSA}}) +\end{cases}$$ +4. Select the desired hash thanks to a multiplexer gate +$$ \mathsf{h} = MUX(\mathsf{h_{ZSA}}, \mathsf{h_{ZEC}}, \mathsf{AssetBase} == \mathcal{V}^{\mathsf{Orchard}})$$ + +![](./zsa-note-commit.png) + diff --git a/book/src/design/circuit/zsa-note-commit.png b/book/src/design/circuit/zsa-note-commit.png new file mode 100644 index 000000000..88cfea04d Binary files /dev/null and b/book/src/design/circuit/zsa-note-commit.png differ diff --git a/book/src/design/commitments.md b/book/src/design/commitments.md index adb83b319..9a3afcae0 100644 --- a/book/src/design/commitments.md +++ b/book/src/design/commitments.md @@ -12,7 +12,15 @@ randomness. We instantiate $\mathit{HomomorphicCommit}$ with a Pedersen commitment, and use it for value commitments: -$$\mathsf{cv} = \mathit{HomomorphicCommit}^{\mathsf{cv}}_{\mathsf{rcv}}(v)$$ +$$\begin{cases} +\mathsf{cv^{Sapling}} &= \mathit{HomomorphicCommit}^{\mathsf{Sapling}}_{\mathsf{rcv}}(\mathsf{v}) \\ +&= [\mathsf{v}]\,\mathcal{V}^{\mathsf{Sapling}} + [\mathsf{rcv}]\,\mathcal{R}^{\mathsf{Sapling}} \\ +\\ +\mathsf{cv^{Orchard}} &= \mathit{HomomorphicCommit}^{\mathsf{Orchard}}_{\mathsf{rcv}}(\mathsf{v}) \\ +&= [\mathsf{v}]\,\mathcal{V}^{\mathsf{Orchard}} + [\mathsf{rcv}]\,\mathcal{R}^{\mathsf{Orchard}} \\ +\\ +\mathsf{cv^{ZSA}} &= [\mathsf{v}]\,\mathsf{AssetBase} + [\mathsf{rcv}]\,\mathcal{R}^{\mathsf{Orchard}} \\ +\end{cases}$$ We instantiate $\mathit{Commit}$ and $\mathit{ShortCommit}$ with Sinsemilla, and use them for all other commitments: diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index f9a11badb..936571978 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -255,3 +255,28 @@ design) does not achieve **Faerie Resistance** for an adversary that knows the r full viewing key ($\psi$ could be brute-forced to cancel out $F_{\mathsf{nk}}(\rho)$, causing a collision), and the other variants require assuming $\mathit{Coll}_F$ as mentioned above. + +## Nullifiers for split notes (OrchardZSA) + +For split notes in OrchardZSA, we have slightly modified the nullifier equation as follows: + +$$\mathsf{nf} = \mathsf{Extract}_{\mathbb{P}}\big([(F_{\mathsf{nk}}(\rho) + \psi_{split}) \bmod{p}] \mathcal{G} + \mathsf{cm} + \mathcal{L}^{Orchard}\big),$$ + +where: + +- $F$ is a keyed circuit-efficient PRF instantiated using the Poseidon hash function. +- $\rho$ is unique to this output. Given that an action + consists of a single spend and a single output, we set $\rho$ to be the nullifier of the + spent note. +- $\psi_{split}$ is sender-controlled randomness. It is not required to be unique, and in practice + is derived from both $\rho$ and a sender-selected random value $\mathsf{rseed}_{split}$ + (distinct from $\mathsf{rseed}$): + $$\psi_{split} = \mathit{KDF}^\psi(\rho, \mathsf{rseed}_{split}).$$ +- $\mathcal{G}$ is a fixed independent base. +- $\mathsf{Extract}_{\mathbb{P}}$ extracts the $x$-coordinate of a Pallas curve point. +- $\mathcal{L}^{Orchard}$ is a fixed independent base. + +### Rationale + +By varying $\mathsf{rseed}_{split}$, split note nullifiers derived +from the same note can be made distinct from each other while appearing random. diff --git a/src/action.rs b/src/action.rs index 04bcc2089..d21d2baae 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,6 +1,7 @@ use memuse::DynamicUsage; use crate::{ + domain::OrchardDomainCommon, note::{ExtractedNoteCommitment, Nullifier, Rho, TransmittedNoteCiphertext}, primitives::redpallas::{self, SpendAuth}, value::ValueCommitment, @@ -11,7 +12,7 @@ use crate::{ /// This both creates a note (adding a commitment to the global ledger), and consumes /// some note created prior to this action (adding a nullifier to the global ledger). #[derive(Debug, Clone)] -pub struct Action { +pub struct Action { /// The nullifier of the note being spent. nf: Nullifier, /// The randomized verification key for the note being spent. @@ -19,22 +20,22 @@ pub struct Action { /// A commitment to the new note being created. cmx: ExtractedNoteCommitment, /// The transmitted note ciphertext. - encrypted_note: TransmittedNoteCiphertext, + encrypted_note: TransmittedNoteCiphertext, /// A commitment to the net value created or consumed by this action. cv_net: ValueCommitment, /// The authorization for this action. authorization: A, } -impl Action { +impl Action { /// Constructs an `Action` from its constituent parts. pub fn from_parts( nf: Nullifier, rk: redpallas::VerificationKey, cmx: ExtractedNoteCommitment, - encrypted_note: TransmittedNoteCiphertext, + encrypted_note: TransmittedNoteCiphertext, cv_net: ValueCommitment, - authorization: T, + authorization: A, ) -> Self { Action { nf, @@ -62,7 +63,7 @@ impl Action { } /// Returns the encrypted note ciphertext. - pub fn encrypted_note(&self) -> &TransmittedNoteCiphertext { + pub fn encrypted_note(&self) -> &TransmittedNoteCiphertext { &self.encrypted_note } @@ -77,12 +78,12 @@ impl Action { } /// Returns the authorization for this action. - pub fn authorization(&self) -> &T { + pub fn authorization(&self) -> &A { &self.authorization } /// Transitions this action from one authorization state to another. - pub fn map(self, step: impl FnOnce(T) -> U) -> Action { + pub fn map(self, step: impl FnOnce(A) -> U) -> Action { Action { nf: self.nf, rk: self.rk, @@ -94,7 +95,7 @@ impl Action { } /// Transitions this action from one authorization state to another. - pub fn try_map(self, step: impl FnOnce(T) -> Result) -> Result, E> { + pub fn try_map(self, step: impl FnOnce(A) -> Result) -> Result, E> { Ok(Action { nf: self.nf, rk: self.rk, @@ -106,7 +107,7 @@ impl Action { } } -impl DynamicUsage for Action> { +impl DynamicUsage for Action, D> { #[inline(always)] fn dynamic_usage(&self) -> usize { 0 @@ -127,10 +128,13 @@ pub(crate) mod testing { use proptest::prelude::*; + use zcash_note_encryption_zsa::NoteEncryption; + use crate::{ + domain::{OrchardDomain, OrchardDomainCommon}, note::{ - commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, - testing::arb_note, TransmittedNoteCiphertext, + asset_base::testing::arb_asset_base, commitment::ExtractedNoteCommitment, + nullifier::testing::arb_nullifier, testing::arb_note, Note, TransmittedNoteCiphertext, }, primitives::redpallas::{ self, @@ -141,66 +145,92 @@ pub(crate) mod testing { use super::Action; - prop_compose! { - /// Generate an action without authorization data. - pub fn arb_unauthorized_action(spend_value: NoteValue, output_value: NoteValue)( - nf in arb_nullifier(), - rk in arb_spendauth_verification_key(), - note in arb_note(output_value), - ) -> Action<()> { - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let cv_net = ValueCommitment::derive( - spend_value - output_value, - ValueCommitTrapdoor::zero() - ); - // FIXME: make a real one from the note. - let encrypted_note = TransmittedNoteCiphertext { - epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 580], - out_ciphertext: [0u8; 80] - }; - Action { - nf, - rk, - cmx, - encrypted_note, - cv_net, - authorization: () + /// `ActionArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol flavors + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct ActionArb { + phantom: std::marker::PhantomData, + } + + impl ActionArb { + fn encrypt_note( + note: Note, + memo: Vec, + cmx: &ExtractedNoteCommitment, + cv_net: &ValueCommitment, + rng: &mut R, + ) -> TransmittedNoteCiphertext { + let encryptor = + NoteEncryption::>::new(None, note, memo.try_into().unwrap()); + + TransmittedNoteCiphertext { + epk_bytes: encryptor.epk().to_bytes().0, + enc_ciphertext: encryptor.encrypt_note_plaintext(), + out_ciphertext: encryptor.encrypt_outgoing_plaintext(cv_net, cmx, rng), + } + } + + prop_compose! { + /// Generate an action without authorization data. + pub fn arb_unauthorized_action(spend_value: NoteValue, output_value: NoteValue)( + nf in arb_nullifier(), + rk in arb_spendauth_verification_key(), + note in arb_note(output_value), + asset in arb_asset_base(), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + memo in prop::collection::vec(prop::num::u8::ANY, 512), + ) -> Action<(), D> { + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let cv_net = ValueCommitment::derive( + spend_value - output_value, + ValueCommitTrapdoor::zero(), + asset + ); + + let mut rng = StdRng::from_seed(rng_seed); + let encrypted_note = Self::encrypt_note(note, memo, &cmx, &cv_net, &mut rng); + + Action { + nf, + rk, + cmx, + encrypted_note, + cv_net, + authorization: () + } } } - } - prop_compose! { - /// Generate an action with invalid (random) authorization data. - pub fn arb_action(spend_value: NoteValue, output_value: NoteValue)( - nf in arb_nullifier(), - sk in arb_spendauth_signing_key(), - note in arb_note(output_value), - rng_seed in prop::array::uniform32(prop::num::u8::ANY), - fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - ) -> Action> { - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let cv_net = ValueCommitment::derive( - spend_value - output_value, - ValueCommitTrapdoor::zero() - ); - - // FIXME: make a real one from the note. - let encrypted_note = TransmittedNoteCiphertext { - epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 580], - out_ciphertext: [0u8; 80] - }; - - let rng = StdRng::from_seed(rng_seed); - - Action { - nf, - rk: redpallas::VerificationKey::from(&sk), - cmx, - encrypted_note, - cv_net, - authorization: sk.sign(rng, &fake_sighash), + prop_compose! { + /// Generate an action with invalid (random) authorization data. + pub fn arb_action(spend_value: NoteValue, output_value: NoteValue)( + nf in arb_nullifier(), + sk in arb_spendauth_signing_key(), + note in arb_note(output_value), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY), + asset in arb_asset_base(), + memo in prop::collection::vec(prop::num::u8::ANY, 512), + ) -> Action, D> { + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let cv_net = ValueCommitment::derive( + spend_value - output_value, + ValueCommitTrapdoor::zero(), + asset + ); + + let mut rng = StdRng::from_seed(rng_seed); + + let encrypted_note = Self::encrypt_note(note, memo, &cmx, &cv_net, &mut rng); + + Action { + nf, + rk: redpallas::VerificationKey::from(&sk), + cmx, + encrypted_note, + cv_net, + authorization: sk.sign(rng, &fake_sighash), + } } } } diff --git a/src/asset_record.rs b/src/asset_record.rs new file mode 100644 index 000000000..b3af557ca --- /dev/null +++ b/src/asset_record.rs @@ -0,0 +1,28 @@ +//! Structs and logic related to aggregated information about an asset. + +use crate::{value::NoteValue, Note}; + +/// Represents aggregated information about an asset, including its supply, finalization status, +/// and reference note. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct AssetRecord { + /// The amount of the asset. + pub amount: NoteValue, + + /// Whether or not the asset is finalized. + pub is_finalized: bool, + + /// A reference note + pub reference_note: Note, +} + +impl AssetRecord { + /// Creates a new [`AssetRecord`] instance. + pub fn new(amount: NoteValue, is_finalized: bool, reference_note: Note) -> Self { + Self { + amount, + is_finalized, + reference_note, + } + } +} diff --git a/src/builder.rs b/src/builder.rs index 37bdc3883..88890e5cb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2,6 +2,7 @@ use core::fmt; use core::iter; +use std::collections::HashMap; use std::fmt::Display; use ff::Field; @@ -9,17 +10,22 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; +use zcash_note_encryption_zsa::NoteEncryption; + +use crate::builder::BuildError::{BurnNative, BurnZero}; +use crate::orchard_flavor::{OrchardVanilla, OrchardZSA}; use crate::{ action::Action, address::Address, - bundle::{Authorization, Authorized, Bundle, Flags}, - circuit::{Circuit, Instance, Proof, ProvingKey}, + bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, + circuit::{Circuit, Instance, Proof, ProvingKey, Witnesses}, + domain::{OrchardDomain, OrchardDomainCommon}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, - note::{Note, Rho, TransmittedNoteCiphertext}, - note_encryption::OrchardNoteEncryption, + note::{AssetBase, Note, Rho, TransmittedNoteCiphertext}, + orchard_flavor::{Flavor, OrchardFlavor}, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -45,17 +51,23 @@ pub enum BundleType { } impl BundleType { - /// The default bundle type has all flags enabled, and does not require a bundle to be produced - /// if no spends or outputs have been added to the bundle. - pub const DEFAULT: BundleType = BundleType::Transactional { - flags: Flags::ENABLED, + /// The default bundle type has all flags enabled, ZSA disabled, and does not require a bundle + /// to be produced. + pub const DEFAULT_VANILLA: BundleType = BundleType::Transactional { + flags: Flags::ENABLED_WITHOUT_ZSA, + bundle_required: false, + }; + + /// The default bundle with all flags enabled, including ZSA. + pub const DEFAULT_ZSA: BundleType = BundleType::Transactional { + flags: Flags::ENABLED_WITH_ZSA, bundle_required: false, }; /// The DISABLED bundle type does not permit any bundle to be produced, and when used in the /// builder will prevent any spends or outputs from being added. pub const DISABLED: BundleType = BundleType::Transactional { - flags: Flags::from_parts(false, false), + flags: Flags::from_parts(false, false, false), bundle_required: false, }; @@ -102,7 +114,7 @@ impl BundleType { pub fn flags(&self) -> Flags { match self { BundleType::Transactional { flags, .. } => *flags, - BundleType::Coinbase => Flags::SPENDS_DISABLED, + BundleType::Coinbase => Flags::SPENDS_DISABLED_WITHOUT_ZSA, } } } @@ -130,6 +142,14 @@ pub enum BuildError { DuplicateSignature, /// The bundle being constructed violated the construction rules for the requested bundle type. BundleTypeNotSatisfiable, + /// Native asset cannot be burned + BurnNative, + /// The value to be burned cannot be zero + BurnZero, + /// The asset to be burned is duplicated. + BurnDuplicateAsset, + /// There is no available split note for this asset. + NoSplitNoteAvailable, } impl Display for BuildError { @@ -149,6 +169,10 @@ impl Display for BuildError { AnchorMismatch => { f.write_str("All spends must share the anchor requested for the transaction.") } + BurnNative => f.write_str("Burning is only possible for non-native assets"), + BurnZero => f.write_str("Burning is not possible for zero values"), + BurnDuplicateAsset => f.write_str("Duplicate assets are not allowed when burning"), + NoSplitNoteAvailable => f.write_str("No split note has been provided for this asset"), } } } @@ -204,13 +228,15 @@ impl Display for OutputError { impl std::error::Error for OutputError {} /// Information about a specific note to be spent in an [`Action`]. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SpendInfo { pub(crate) dummy_sk: Option, pub(crate) fvk: FullViewingKey, pub(crate) scope: Scope, pub(crate) note: Note, pub(crate) merkle_path: MerklePath, + // a flag to indicate whether the value of the note will be counted in the `ValueSum` of the action. + pub(crate) split_flag: bool, } impl SpendInfo { @@ -223,7 +249,12 @@ impl SpendInfo { /// Returns `None` if the `fvk` does not own the `note`. /// /// [`Builder::add_spend`]: Builder::add_spend - pub fn new(fvk: FullViewingKey, note: Note, merkle_path: MerklePath) -> Option { + pub fn new( + fvk: FullViewingKey, + note: Note, + merkle_path: MerklePath, + split_flag: bool, + ) -> Option { let scope = fvk.scope_for_address(¬e.recipient())?; Some(SpendInfo { dummy_sk: None, @@ -231,14 +262,15 @@ impl SpendInfo { scope, note, merkle_path, + split_flag, }) } /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(rng: &mut impl RngCore) -> Self { - let (sk, fvk, note) = Note::dummy(rng, None); + fn dummy(asset: AssetBase, rng: &mut impl RngCore) -> Self { + let (sk, fvk, note) = Note::dummy(rng, None, asset); let merkle_path = MerklePath::dummy(rng); SpendInfo { @@ -249,6 +281,25 @@ impl SpendInfo { scope: Scope::External, note, merkle_path, + split_flag: false, + } + } + + /// Creates a split spend, which is identical to origin normal spend except that + /// `rseed_split_note` contains a random seed. In addition, the split_flag is raised. + /// + /// Defined in [Transfer and Burn of Zcash Shielded Assets ZIP-0226 § Split Notes (DRAFT PR)][TransferZSA]. + /// + /// [TransferZSA]: https://zips.z.cash/zip-0226#split-notes + fn create_split_spend(&self, rng: &mut impl RngCore) -> Self { + SpendInfo { + dummy_sk: None, + fvk: self.fvk.clone(), + // We use external scope to avoid unnecessary derivations + scope: Scope::External, + note: self.note.create_split_note(rng), + merkle_path: self.merkle_path.clone(), + split_flag: true, } } @@ -264,11 +315,12 @@ impl SpendInfo { } /// Information about a specific output to receive funds in an [`Action`]. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct OutputInfo { ovk: Option, recipient: Address, value: NoteValue, + asset: AssetBase, memo: [u8; 512], } @@ -278,12 +330,14 @@ impl OutputInfo { ovk: Option, recipient: Address, value: NoteValue, + asset: AssetBase, memo: Option<[u8; 512]>, ) -> Self { Self { ovk, recipient, value, + asset, memo: memo.unwrap_or_else(|| { let mut memo = [0; 512]; memo[0] = 0xf6; @@ -295,11 +349,11 @@ impl OutputInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - pub fn dummy(rng: &mut impl RngCore) -> Self { + pub fn dummy(rng: &mut impl RngCore, asset: AssetBase) -> Self { let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); let recipient = fvk.address_at(0u32, Scope::External); - Self::new(None, recipient, NoteValue::zero(), None) + Self::new(None, recipient, NoteValue::zero(), asset, None) } } @@ -321,8 +375,15 @@ impl ActionInfo { } /// Returns the value sum for this action. + /// Split notes do not contribute to the value sum. fn value_sum(&self) -> ValueSum { - self.spend.note.value() - self.output.value + let spent_value = if self.spend.split_flag { + NoteValue::zero() + } else { + self.spend.note.value() + }; + + spent_value - self.output.value } /// Builds the action. @@ -330,9 +391,23 @@ impl ActionInfo { /// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend]. /// /// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend - fn build(self, mut rng: impl RngCore) -> (Action, Circuit) { + /// + /// # Panics + /// + /// Panics if the asset types of the spent and output notes do not match. + fn build( + self, + mut rng: impl RngCore, + ) -> (Action, Witnesses) { + assert_eq!( + self.spend.note.asset(), + self.output.asset, + "spend and recipient note types must be equal" + ); + let v_net = self.value_sum(); - let cv_net = ValueCommitment::derive(v_net, self.rcv.clone()); + let asset = self.output.asset; + let cv_net = ValueCommitment::derive(v_net, self.rcv, asset); let nf_old = self.spend.note.nullifier(&self.spend.fvk); let rho = Rho::from_nf_old(nf_old); @@ -340,11 +415,18 @@ impl ActionInfo { let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let note = Note::new(self.output.recipient, self.output.value, rho, &mut rng); + let note = Note::new( + self.output.recipient, + self.output.value, + self.output.asset, + rho, + &mut rng, + ); let cm_new = note.commitment(); let cmx = cm_new.into(); - let encryptor = OrchardNoteEncryption::new(self.output.ovk, note, self.output.memo); + let encryptor = + NoteEncryption::>::new(self.output.ovk, note, self.output.memo); let encrypted_note = TransmittedNoteCiphertext { epk_bytes: encryptor.epk().to_bytes().0, @@ -364,7 +446,7 @@ impl ActionInfo { parts: SigningParts { ak, alpha }, }, ), - Circuit::from_action_context_unchecked(self.spend, note, alpha, self.rcv), + Witnesses::from_action_context_unchecked(self.spend, note, alpha, self.rcv), ) } } @@ -372,7 +454,7 @@ impl ActionInfo { /// Type alias for an in-progress bundle that has no proofs or signatures. /// /// This is returned by [`Builder::build`]. -pub type UnauthorizedBundle = Bundle, V>; +pub type UnauthorizedBundle = Bundle, V, D>; /// Metadata about a bundle created by [`bundle`] or [`Builder::build`] that is not /// necessarily recoverable from the bundle itself. @@ -424,12 +506,16 @@ impl BundleMetadata { } } +/// A tuple containing an in-progress bundle with no proofs or signatures, and its associated metadata. +pub type UnauthorizedBundleWithMetadata = (UnauthorizedBundle, BundleMetadata); + /// A builder that constructs a [`Bundle`] from a set of notes to be spent, and outputs /// to receive funds. #[derive(Debug)] pub struct Builder { spends: Vec, outputs: Vec, + burn: HashMap, bundle_type: BundleType, anchor: Anchor, } @@ -440,6 +526,7 @@ impl Builder { Builder { spends: vec![], outputs: vec![], + burn: HashMap::new(), bundle_type, anchor, } @@ -448,14 +535,14 @@ impl Builder { /// Adds a note to be spent in this transaction. /// /// - `note` is a spendable note, obtained by trial-decrypting an [`Action`] using the - /// [`zcash_note_encryption`] crate instantiated with [`OrchardDomain`]. + /// [`zcash_note_encryption_zsa`] crate instantiated with [`OrchardDomain`]. /// - `merkle_path` can be obtained using the [`incrementalmerkletree`] crate /// instantiated with [`MerkleHashOrchard`]. /// /// Returns an error if the given Merkle path does not have the required anchor for /// the given note. /// - /// [`OrchardDomain`]: crate::note_encryption::OrchardDomain + /// [`OrchardDomain`]: crate::domain::OrchardDomain /// [`MerkleHashOrchard`]: crate::tree::MerkleHashOrchard pub fn add_spend( &mut self, @@ -468,7 +555,7 @@ impl Builder { return Err(SpendError::SpendsDisabled); } - let spend = SpendInfo::new(fvk, note, merkle_path).ok_or(SpendError::FvkMismatch)?; + let spend = SpendInfo::new(fvk, note, merkle_path, false).ok_or(SpendError::FvkMismatch)?; // Consistency check: all anchors must be equal. if !spend.has_matching_anchor(&self.anchor) { @@ -486,6 +573,7 @@ impl Builder { ovk: Option, recipient: Address, value: NoteValue, + asset: AssetBase, memo: Option<[u8; 512]>, ) -> Result<(), OutputError> { let flags = self.bundle_type.flags(); @@ -494,11 +582,32 @@ impl Builder { } self.outputs - .push(OutputInfo::new(ovk, recipient, value, memo)); + .push(OutputInfo::new(ovk, recipient, value, asset, memo)); Ok(()) } + /// Add an instruction to burn a given amount of a specific asset. + pub fn add_burn(&mut self, asset: AssetBase, value: NoteValue) -> Result<(), BuildError> { + use std::collections::hash_map::Entry; + + if asset.is_native().into() { + return Err(BurnNative); + } + + if value.inner() == 0 { + return Err(BurnZero); + } + + match self.burn.entry(asset) { + Entry::Occupied(_) => Err(BuildError::BurnDuplicateAsset), + Entry::Vacant(entry) => { + entry.insert(value); + Ok(()) + } + } + } + /// Returns the action spend components that will be produced by the /// transaction being constructed pub fn spends(&self) -> &Vec> { @@ -511,7 +620,7 @@ impl Builder { &self.outputs } - /// The net value of the bundle to be built. The value of all spends, + /// The net native (ZEC) value of the bundle to be built. The value of all spends, /// minus the value of all outputs. /// /// Useful for balancing a transaction, as the value balance of an individual bundle @@ -525,13 +634,15 @@ impl Builder { let value_balance = self .spends .iter() + .filter(|spend| spend.note.asset().is_native().into()) .map(|spend| spend.note.value() - NoteValue::zero()) .chain( self.outputs .iter() + .filter(|output| output.asset.is_native().into()) .map(|output| NoteValue::zero() - output.value), ) - .fold(Some(ValueSum::zero()), |acc, note_value| acc? + note_value) + .try_fold(ValueSum::zero(), |acc, note_value| acc + note_value) .ok_or(OverflowError)?; i64::try_from(value_balance).and_then(|i| V::try_from(i).map_err(|_| value::OverflowError)) } @@ -540,31 +651,101 @@ impl Builder { /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. - pub fn build>( + pub fn build, FL: OrchardFlavor>( self, rng: impl RngCore, - ) -> Result, BundleMetadata)>, BuildError> { + ) -> Result, BuildError> { bundle( rng, self.anchor, self.bundle_type, self.spends, self.outputs, + self.burn, ) } } +/// The index of the attached spend or output in the bundle. +/// None indicates a dummy note. +/// The index is used to track the position of the note in the bundle. +type MetadataIdx = Option; + +/// Partition a list of spends and outputs by note types. +/// Method creates single dummy ZEC note if spends and outputs are both empty. +#[allow(clippy::type_complexity)] +fn partition_by_asset( + spends: &[SpendInfo], + outputs: &[OutputInfo], + rng: &mut impl RngCore, +) -> HashMap< + AssetBase, + ( + Vec<(SpendInfo, MetadataIdx)>, + Vec<(OutputInfo, MetadataIdx)>, + ), +> { + let mut hm = HashMap::new(); + + for (i, s) in spends.iter().enumerate() { + hm.entry(s.note.asset()) + .or_insert((vec![], vec![])) + .0 + .push((s.clone(), Some(i))); + } + + for (i, o) in outputs.iter().enumerate() { + hm.entry(o.asset) + .or_insert((vec![], vec![])) + .1 + .push((o.clone(), Some(i))); + } + + if hm.is_empty() { + // dummy_spend should not be included in the indexing and marked as None. + hm.insert( + AssetBase::native(), + ( + vec![(SpendInfo::dummy(AssetBase::native(), rng), None)], + vec![], + ), + ); + } + + hm +} + +/// Returns the appropriate SpendInfo for padding. +fn pad_spend( + spend: Option<&SpendInfo>, + asset: AssetBase, + mut rng: impl RngCore, +) -> Result { + if asset.is_native().into() { + // For native asset, extends with dummy notes + Ok(SpendInfo::dummy(AssetBase::native(), &mut rng)) + } else { + // For ZSA asset, extends with split_notes. + // If SpendInfo is none, return an error (no split note are available for this asset) + spend + .map(|s| s.create_split_spend(&mut rng)) + .ok_or(BuildError::NoSplitNoteAvailable) + } +} + /// Builds a bundle containing the given spent notes and outputs. /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. -pub fn bundle>( +#[allow(clippy::type_complexity)] +pub fn bundle, FL: OrchardFlavor>( mut rng: impl RngCore, anchor: Anchor, bundle_type: BundleType, spends: Vec, outputs: Vec, -) -> Result, BundleMetadata)>, BuildError> { + burn: HashMap, +) -> Result, BuildError> { let flags = bundle_type.flags(); let num_requested_spends = spends.len(); @@ -583,45 +764,75 @@ pub fn bundle>( return Err(BuildError::OutputsDisabled); } - let num_actions = bundle_type - .num_actions(num_requested_spends, num_requested_outputs) - .map_err(|_| BuildError::BundleTypeNotSatisfiable)?; - // Pair up the spends and outputs, extending with dummy values as necessary. let (pre_actions, bundle_meta) = { - let mut indexed_spends = spends - .into_iter() - .chain(iter::repeat_with(|| SpendInfo::dummy(&mut rng))) - .enumerate() - .take(num_actions) - .collect::>(); - - let mut indexed_outputs = outputs - .into_iter() - .chain(iter::repeat_with(|| OutputInfo::dummy(&mut rng))) - .enumerate() - .take(num_actions) - .collect::>(); + // Use Vec::with_capacity().extend(...) instead of .collect() to avoid reallocations, + // as we can estimate the vector size beforehand. + let mut indexed_spends_outputs = + Vec::with_capacity(spends.len().max(outputs.len()).max(MIN_ACTIONS)); + + indexed_spends_outputs.extend( + partition_by_asset(&spends, &outputs, &mut rng) + .into_iter() + .flat_map(|(asset, (spends, outputs))| { + let num_asset_pre_actions = spends.len().max(outputs.len()); + + let first_spend = spends.first().map(|(s, _)| s.clone()); + + let mut indexed_spends = spends + .into_iter() + .chain(iter::repeat_with(|| { + ( + pad_spend(first_spend.as_ref(), asset, &mut rng) + .unwrap_or_else(|err| panic!("{:?}", err)), + None, + ) + })) + .take(num_asset_pre_actions) + .collect::>(); + + let mut indexed_outputs = outputs + .into_iter() + .chain(iter::repeat_with(|| { + (OutputInfo::dummy(&mut rng, asset), None) + })) + .take(num_asset_pre_actions) + .collect::>(); + + // Shuffle the spends and outputs, so that learning the position of a + // specific spent note or output note doesn't reveal anything on its own about + // the meaning of that note in the transaction context. + indexed_spends.shuffle(&mut rng); + indexed_outputs.shuffle(&mut rng); + + assert_eq!(indexed_spends.len(), indexed_outputs.len()); + + indexed_spends.into_iter().zip(indexed_outputs) + }), + ); - // Shuffle the spends and outputs, so that learning the position of a - // specific spent note or output note doesn't reveal anything on its own about - // the meaning of that note in the transaction context. - indexed_spends.shuffle(&mut rng); - indexed_outputs.shuffle(&mut rng); + indexed_spends_outputs.extend( + iter::repeat_with(|| { + ( + (SpendInfo::dummy(AssetBase::native(), &mut rng), None), + (OutputInfo::dummy(&mut rng, AssetBase::native()), None), + ) + }) + .take(MIN_ACTIONS.saturating_sub(indexed_spends_outputs.len())), + ); let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); - let pre_actions = indexed_spends + let pre_actions = indexed_spends_outputs .into_iter() - .zip(indexed_outputs.into_iter()) .enumerate() - .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { + .map(|(action_idx, ((spend, spend_idx), (output, out_idx)))| { // Record the post-randomization spend location - if spend_idx < num_requested_spends { + if let Some(spend_idx) = spend_idx { bundle_meta.spend_indices[spend_idx] = action_idx; } // Record the post-randomization output location - if out_idx < num_requested_outputs { + if let Some(out_idx) = out_idx { bundle_meta.output_indices[out_idx] = action_idx; } @@ -633,16 +844,17 @@ pub fn bundle>( }; // Determine the value balance for this bundle, ensuring it is valid. - let value_balance = pre_actions + let native_value_balance: i64 = pre_actions .iter() + .filter(|action| action.spend.note.asset().is_native().into()) .fold(Some(ValueSum::zero()), |acc, action| { acc? + action.value_sum() }) - .ok_or(OverflowError)?; + .ok_or(OverflowError)? + .into()?; - let result_value_balance: V = i64::try_from(value_balance) - .map_err(BuildError::ValueSum) - .and_then(|i| V::try_from(i).map_err(|_| BuildError::ValueSum(value::OverflowError)))?; + let result_value_balance = V::try_from(native_value_balance) + .map_err(|_| BuildError::ValueSum(value::OverflowError))?; // Compute the transaction binding signing key. let bsk = pre_actions @@ -652,36 +864,50 @@ pub fn bundle>( .into_bsk(); // Create the actions. - let (actions, circuits): (Vec<_>, Vec<_>) = + let (actions, witnesses): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); + let burn = burn + .into_iter() + .map(|(asset, value)| { + Ok(( + asset, + NoteValue::from_raw( + u64::try_from(i128::from(value)) + .map_err(|_| BuildError::ValueSum(OverflowError))?, + ), + )) + }) + .collect::, BuildError>>()?; + // Verify that bsk and bvk are consistent. - let bvk = (actions.iter().map(|a| a.cv_net()).sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero())) - .into_bvk(); + let bvk = derive_bvk(&actions, native_value_balance, burn.iter().cloned()); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); - Ok(NonEmpty::from_vec(actions).map(|actions| { - ( - Bundle::from_parts( - actions, - flags, - result_value_balance, - anchor, - InProgress { - proof: Unproven { circuits }, - sigs: Unauthorized { bsk }, + Ok(( + Bundle::from_parts( + // `actions` is never empty. It contains at least MIN_ACTIONS=2 actions. + NonEmpty::from_vec(actions).unwrap(), + flags, + result_value_balance, + burn, + anchor, + InProgress { + proof: Unproven { + witnesses, + circuit_flavor: FL::FLAVOR, }, - ), - bundle_meta, - ) - })) + sigs: Unauthorized { bsk }, + }, + ), + bundle_meta, + )) } /// Marker trait representing bundle signatures in the process of being created. pub trait InProgressSignatures: fmt::Debug { /// The authorization type of an Orchard action in the process of being authorized. - type SpendAuth: fmt::Debug; + type SpendAuth: fmt::Debug + Clone; } /// Marker for a bundle in the process of being built. @@ -691,6 +917,19 @@ pub struct InProgress { sigs: S, } +impl InProgress { + /// Mutate the proof using the provided function. + pub fn map_proof(self, f: F) -> InProgress + where + F: FnOnce(P) -> P2, + { + InProgress { + proof: f(self.proof), + sigs: self.sigs, + } + } +} + impl Authorization for InProgress { type SpendAuth = S::SpendAuth; } @@ -700,7 +939,8 @@ impl Authorization for InProgress /// This struct contains the private data needed to create a [`Proof`] for a [`Bundle`]. #[derive(Clone, Debug)] pub struct Unproven { - circuits: Vec, + witnesses: Vec, + circuit_flavor: Flavor, } impl InProgress { @@ -711,17 +951,42 @@ impl InProgress { instances: &[Instance], rng: impl RngCore, ) -> Result { - Proof::create(pk, &self.proof.circuits, instances, rng) + match self.proof.circuit_flavor { + Flavor::OrchardVanillaFlavor => { + let circuits = self + .proof + .witnesses + .iter() + .map(|witnesses| Circuit:: { + witnesses: witnesses.clone(), + phantom: std::marker::PhantomData, + }) + .collect::>>(); + Proof::create(pk, &circuits, instances, rng) + } + Flavor::OrchardZSAFlavor => { + let circuits = self + .proof + .witnesses + .iter() + .map(|witnesses| Circuit:: { + witnesses: witnesses.clone(), + phantom: std::marker::PhantomData, + }) + .collect::>>(); + Proof::create(pk, &circuits, instances, rng) + } + } } } -impl Bundle, V> { +impl Bundle, V, FL> { /// Creates the proof for this bundle. pub fn create_proof( self, pk: &ProvingKey, mut rng: impl RngCore, - ) -> Result, V>, BuildError> { + ) -> Result, V, FL>, BuildError> { let instances: Vec<_> = self .actions() .iter() @@ -787,7 +1052,7 @@ impl InProgressSignatures for PartiallyAuthorized { /// A heisen[`Signature`] for a particular [`Action`]. /// /// [`Signature`]: redpallas::Signature -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum MaybeSigned { /// The information needed to sign this [`Action`]. SigningMetadata(SigningParts), @@ -804,7 +1069,7 @@ impl MaybeSigned { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Loads the sighash into this bundle, preparing it for signing. /// /// This API ensures that all signatures are created over the same sighash. @@ -812,7 +1077,7 @@ impl Bundle, V> { self, mut rng: R, sighash: [u8; 32], - ) -> Bundle, V> { + ) -> Bundle, V, D> { self.map_authorization( &mut rng, |rng, _, SigningMetadata { dummy_ask, parts }| { @@ -833,7 +1098,7 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Applies signatures to this bundle, in order to authorize it. /// /// This is a helper method that wraps [`Bundle::prepare`], [`Bundle::sign`], and @@ -843,7 +1108,7 @@ impl Bundle, V> { mut rng: R, sighash: [u8; 32], signing_keys: &[SpendAuthorizingKey], - ) -> Result, BuildError> { + ) -> Result, BuildError> { signing_keys .iter() .fold(self.prepare(&mut rng, sighash), |partial, ask| { @@ -853,7 +1118,7 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Signs this bundle with the given [`SpendAuthorizingKey`]. /// /// This will apply signatures for all notes controlled by this spending key. @@ -916,11 +1181,11 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Finalizes this bundle, enabling it to be included in a transaction. /// /// Returns an error if any signatures are missing. - pub fn finalize(self) -> Result, BuildError> { + pub fn finalize(self) -> Result, BuildError> { self.try_map_authorization( &mut (), |_, _, maybe| maybe.finalize(), @@ -978,12 +1243,15 @@ pub mod testing { use proptest::collection::vec; use proptest::prelude::*; + use crate::note::AssetBase; use crate::{ address::testing::arb_address, bundle::{Authorized, Bundle}, circuit::ProvingKey, + domain::OrchardDomainCommon, keys::{testing::arb_spending_key, FullViewingKey, SpendAuthorizingKey, SpendingKey}, note::testing::arb_note, + orchard_flavor::OrchardFlavor, tree::{Anchor, MerkleHashOrchard, MerklePath}, value::{testing::arb_positive_note_value, NoteValue, MAX_NOTE_VALUE}, Address, Note, @@ -1005,33 +1273,34 @@ pub mod testing { sk: SpendingKey, anchor: Anchor, notes: Vec<(Note, MerklePath)>, - output_amounts: Vec<(Address, NoteValue)>, + output_amounts: Vec<(Address, NoteValue, AssetBase)>, } impl ArbitraryBundleInputs { /// Create a bundle from the set of arbitrary bundle inputs. - fn into_bundle>(mut self) -> Bundle { + fn into_bundle + Copy + Into, FL: OrchardFlavor>( + mut self, + ) -> Bundle { let fvk = FullViewingKey::from(&self.sk); - let mut builder = Builder::new(BundleType::DEFAULT, self.anchor); + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, self.anchor); for (note, path) in self.notes.into_iter() { builder.add_spend(fvk.clone(), note, path).unwrap(); } - for (addr, value) in self.output_amounts.into_iter() { + for (addr, value, asset) in self.output_amounts.into_iter() { let scope = fvk.scope_for_address(&addr).unwrap(); let ovk = fvk.to_ovk(scope); builder - .add_output(Some(ovk.clone()), addr, value, None) + .add_output(Some(ovk.clone()), addr, value, asset, None) .unwrap(); } - let pk = ProvingKey::build(); + let pk = ProvingKey::build::(); builder .build(&mut self.rng) .unwrap() - .unwrap() .0 .create_proof(&pk, &mut self.rng) .unwrap() @@ -1042,67 +1311,78 @@ pub mod testing { } } - prop_compose! { - /// Produce a random valid Orchard bundle. - fn arb_bundle_inputs(sk: SpendingKey) - ( - n_notes in 1usize..30, - n_outputs in 1..30, + /// `BuilderArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol variations + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct BuilderArb { + phantom: std::marker::PhantomData, + } - ) - ( - // generate note values that we're certain won't exceed MAX_NOTE_VALUE in total - notes in vec( - arb_positive_note_value(MAX_NOTE_VALUE / n_notes as u64).prop_flat_map(arb_note), - n_notes - ), - output_amounts in vec( - arb_address().prop_flat_map(move |a| { - arb_positive_note_value(MAX_NOTE_VALUE / n_outputs as u64) - .prop_map(move |v| (a, v)) - }), - n_outputs as usize - ), - rng_seed in prop::array::uniform32(prop::num::u8::ANY) - ) -> ArbitraryBundleInputs { - use crate::constants::MERKLE_DEPTH_ORCHARD; - let mut frontier = Frontier::::empty(); - let mut notes_and_auth_paths: Vec<(Note, MerklePath)> = Vec::new(); - - for note in notes.iter() { - let leaf = MerkleHashOrchard::from_cmx(¬e.commitment().into()); - frontier.append(leaf); - - let path = frontier - .witness(|addr| Some(::empty_root(addr.level()))) - .ok() - .flatten() - .expect("we can always construct a correct Merkle path"); - notes_and_auth_paths.push((*note, path.into())); - } + impl BuilderArb { + prop_compose! { + /// Produce a random valid Orchard bundle. + fn arb_bundle_inputs(sk: SpendingKey) + ( + n_notes in 1usize..30, + n_outputs in 1..30, + ) + ( + // generate note values that we're certain won't exceed MAX_NOTE_VALUE in total + notes in vec( + arb_positive_note_value(MAX_NOTE_VALUE / n_notes as u64).prop_flat_map(arb_note), + n_notes + ), + output_amounts in vec( + arb_address().prop_flat_map(move |a| { + arb_positive_note_value(MAX_NOTE_VALUE / n_outputs as u64) + .prop_map(move |v| { + (a,v, AssetBase::native()) + }) + }), + n_outputs as usize, + ), + rng_seed in prop::array::uniform32(prop::num::u8::ANY) + ) -> ArbitraryBundleInputs { + use crate::constants::MERKLE_DEPTH_ORCHARD; + let mut frontier = Frontier::::empty(); + let mut notes_and_auth_paths: Vec<(Note, MerklePath)> = Vec::new(); + + for note in notes.iter() { + let leaf = MerkleHashOrchard::from_cmx(¬e.commitment().into()); + frontier.append(leaf); + + let path = frontier + .witness(|addr| Some(::empty_root(addr.level()))) + .ok() + .flatten() + .expect("we can always construct a correct Merkle path"); + notes_and_auth_paths.push((*note, path.into())); + } - ArbitraryBundleInputs { - rng: StdRng::from_seed(rng_seed), - sk, - anchor: frontier.root().into(), - notes: notes_and_auth_paths, - output_amounts + ArbitraryBundleInputs { + rng: StdRng::from_seed(rng_seed), + sk, + anchor: frontier.root().into(), + notes: notes_and_auth_paths, + output_amounts + } } } - } - /// Produce an arbitrary valid Orchard bundle using a random spending key. - pub fn arb_bundle + Debug>() -> impl Strategy> { - arb_spending_key() - .prop_flat_map(arb_bundle_inputs) - .prop_map(|inputs| inputs.into_bundle::()) - } + /// Produce an arbitrary valid Orchard bundle using a random spending key. + pub fn arb_bundle + Debug + Copy + Into>( + ) -> impl Strategy> { + arb_spending_key() + .prop_flat_map(BuilderArb::::arb_bundle_inputs) + .prop_map(|inputs| inputs.into_bundle::()) + } - /// Produce an arbitrary valid Orchard bundle using a specified spending key. - pub fn arb_bundle_with_key + Debug>( - k: SpendingKey, - ) -> impl Strategy> { - arb_bundle_inputs(k).prop_map(|inputs| inputs.into_bundle::()) + /// Produce an arbitrary valid Orchard bundle using a specified spending key. + pub fn arb_bundle_with_key + Debug + Copy + Into>( + k: SpendingKey, + ) -> impl Strategy> { + BuilderArb::::arb_bundle_inputs(k).prop_map(|inputs| inputs.into_bundle::()) + } } } @@ -1110,20 +1390,22 @@ pub mod testing { mod tests { use rand::rngs::OsRng; - use super::Builder; use crate::{ builder::BundleType, bundle::{Authorized, Bundle}, circuit::ProvingKey, constants::MERKLE_DEPTH_ORCHARD, keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::EMPTY_ROOTS, value::NoteValue, }; - #[test] - fn shielding_bundle() { - let pk = ProvingKey::build(); + use super::Builder; + + fn shielding_bundle() { + let pk = ProvingKey::build::(); let mut rng = OsRng; let sk = SpendingKey::random(&mut rng); @@ -1131,20 +1413,25 @@ mod tests { let recipient = fvk.address_at(0u32, Scope::External); let mut builder = Builder::new( - BundleType::DEFAULT, + BundleType::DEFAULT_VANILLA, EMPTY_ROOTS[MERKLE_DEPTH_ORCHARD].into(), ); builder - .add_output(None, recipient, NoteValue::from_raw(5000), None) + .add_output( + None, + recipient, + NoteValue::from_raw(5000), + AssetBase::native(), + None, + ) .unwrap(); let balance: i64 = builder.value_balance().unwrap(); assert_eq!(balance, -5000); - let bundle: Bundle = builder + let bundle: Bundle = builder .build(&mut rng) .unwrap() - .unwrap() .0 .create_proof(&pk, &mut rng) .unwrap() @@ -1153,4 +1440,14 @@ mod tests { .unwrap(); assert_eq!(bundle.value_balance(), &(-5000)) } + + #[test] + fn shielding_bundle_vanilla() { + shielding_bundle::() + } + + #[test] + fn shielding_bundle_zsa() { + shielding_bundle::() + } } diff --git a/src/bundle.rs b/src/bundle.rs index 02cd697eb..4f67591a8 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -1,6 +1,7 @@ //! Structs related to bundles of Orchard actions. mod batch; +pub mod burn_validation; pub mod commitments; pub use batch::BatchValidator; @@ -10,22 +11,23 @@ use core::fmt; use blake2b_simd::Hash as Blake2bHash; use memuse::DynamicUsage; use nonempty::NonEmpty; -use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; +use zcash_note_encryption_zsa::{try_note_decryption, try_output_recovery_with_ovk}; use crate::{ action::Action, address::Address, bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, circuit::{Instance, Proof, VerifyingKey}, + domain::{OrchardDomain, OrchardDomainCommon}, keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, - note::Note, - note_encryption::OrchardDomain, + note::{AssetBase, Note}, + orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, - value::{ValueCommitTrapdoor, ValueCommitment, ValueSum}, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, }; -impl Action { +impl Action { /// Prepares the public instance for this action, for creating and verifying the /// bundle proof. pub fn to_instance(&self, flags: Flags, anchor: Anchor) -> Instance { @@ -37,6 +39,7 @@ impl Action { cmx: *self.cmx(), enable_spend: flags.spends_enabled, enable_output: flags.outputs_enabled, + enable_zsa: flags.zsa_enabled, } } } @@ -56,37 +59,65 @@ pub struct Flags { /// guaranteed to be dummy notes. If `true`, the created notes may be either real or /// dummy notes. outputs_enabled: bool, + /// Flag denoting whether ZSA transaction is enabled. + /// + /// If `false`, all notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be notes with native asset. + zsa_enabled: bool, } const FLAG_SPENDS_ENABLED: u8 = 0b0000_0001; const FLAG_OUTPUTS_ENABLED: u8 = 0b0000_0010; -const FLAGS_EXPECTED_UNSET: u8 = !(FLAG_SPENDS_ENABLED | FLAG_OUTPUTS_ENABLED); +const FLAG_ZSA_ENABLED: u8 = 0b0000_0100; +const FLAGS_EXPECTED_UNSET: u8 = !(FLAG_SPENDS_ENABLED | FLAG_OUTPUTS_ENABLED | FLAG_ZSA_ENABLED); impl Flags { /// Construct a set of flags from its constituent parts - pub(crate) const fn from_parts(spends_enabled: bool, outputs_enabled: bool) -> Self { + pub(crate) const fn from_parts( + spends_enabled: bool, + outputs_enabled: bool, + zsa_enabled: bool, + ) -> Self { Flags { spends_enabled, outputs_enabled, + zsa_enabled, } } - /// The flag set with both spends and outputs enabled. - pub const ENABLED: Flags = Flags { + /// The flag set with both spends and outputs enabled and ZSA disabled. + pub const ENABLED_WITHOUT_ZSA: Flags = Flags { + spends_enabled: true, + outputs_enabled: true, + zsa_enabled: false, + }; + + /// The flags set with spends, outputs and ZSA enabled. + pub const ENABLED_WITH_ZSA: Flags = Flags { spends_enabled: true, outputs_enabled: true, + zsa_enabled: true, }; - /// The flag set with spends disabled. - pub const SPENDS_DISABLED: Flags = Flags { + /// The flag set with spends and ZSA disabled. + pub const SPENDS_DISABLED_WITHOUT_ZSA: Flags = Flags { spends_enabled: false, outputs_enabled: true, + zsa_enabled: false, + }; + + /// The flag set with spends disabled and ZSA enabled. + pub const SPENDS_DISABLED_WITH_ZSA: Flags = Flags { + spends_enabled: false, + outputs_enabled: true, + zsa_enabled: true, }; /// The flag set with outputs disabled. pub const OUTPUTS_DISABLED: Flags = Flags { spends_enabled: true, outputs_enabled: false, + zsa_enabled: false, }; /// Flag denoting whether Orchard spends are enabled in the transaction. @@ -107,6 +138,14 @@ impl Flags { self.outputs_enabled } + /// Flag denoting whether ZSA transaction is enabled. + /// + /// If `false`, all notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be notes with native asset. + pub fn zsa_enabled(&self) -> bool { + self.zsa_enabled + } + /// Serialize flags to a byte as defined in [Zcash Protocol Spec § 7.1: Transaction /// Encoding And Consensus][txencoding]. /// @@ -119,6 +158,9 @@ impl Flags { if self.outputs_enabled { value |= FLAG_OUTPUTS_ENABLED; } + if self.zsa_enabled { + value |= FLAG_ZSA_ENABLED; + } value } @@ -134,6 +176,7 @@ impl Flags { Some(Self { spends_enabled: value & FLAG_SPENDS_ENABLED != 0, outputs_enabled: value & FLAG_OUTPUTS_ENABLED != 0, + zsa_enabled: value & FLAG_ZSA_ENABLED != 0, }) } else { None @@ -144,31 +187,38 @@ impl Flags { /// Defines the authorization type of an Orchard bundle. pub trait Authorization: fmt::Debug { /// The authorization type of an Orchard action. - type SpendAuth: fmt::Debug; + type SpendAuth: fmt::Debug + Clone; } /// A bundle of actions to be applied to the ledger. #[derive(Clone)] -pub struct Bundle { +pub struct Bundle { /// The list of actions that make up this bundle. - actions: NonEmpty>, + actions: NonEmpty>, /// Orchard-specific transaction-level flags for this bundle. flags: Flags, /// The net value moved out of the Orchard shielded pool. /// /// This is the sum of Orchard spends minus the sum of Orchard outputs. value_balance: V, + /// Assets intended for burning + burn: Vec<(AssetBase, NoteValue)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, + /// Block height after which this Bundle's Actions are invalid by consensus. + /// + /// For the OrchardZSA protocol, `expiry_height` is set to 0, indicating no expiry. + /// This field is reserved for future use. + expiry_height: u32, /// The authorization for this bundle. - authorization: T, + authorization: A, } -impl fmt::Debug for Bundle { +impl fmt::Debug for Bundle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// Helper struct for debug-printing actions without exposing `NonEmpty`. - struct Actions<'a, T>(&'a NonEmpty>); - impl<'a, T: fmt::Debug> fmt::Debug for Actions<'a, T> { + struct Actions<'a, A, D: OrchardDomainCommon>(&'a NonEmpty>); + impl<'a, A: fmt::Debug, D: OrchardDomainCommon> fmt::Debug for Actions<'a, A, D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.0.iter()).finish() } @@ -184,26 +234,29 @@ impl fmt::Debug for Bundle { } } -impl Bundle { +impl Bundle { /// Constructs a `Bundle` from its constituent parts. pub fn from_parts( - actions: NonEmpty>, + actions: NonEmpty>, flags: Flags, value_balance: V, + burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, - authorization: T, + authorization: A, ) -> Self { Bundle { actions, flags, value_balance, + burn, anchor, + expiry_height: 0, authorization, } } /// Returns the list of actions that make up this bundle. - pub fn actions(&self) -> &NonEmpty> { + pub fn actions(&self) -> &NonEmpty> { &self.actions } @@ -219,29 +272,41 @@ impl Bundle { &self.value_balance } + /// Returns assets intended for burning + pub fn burn(&self) -> &Vec<(AssetBase, NoteValue)> { + &self.burn + } + /// Returns the root of the Orchard commitment tree that this bundle commits to. pub fn anchor(&self) -> &Anchor { &self.anchor } + /// Returns the expiry height for this bundle. + pub fn expiry_height(&self) -> u32 { + self.expiry_height + } + /// Returns the authorization for this bundle. /// /// In the case of a `Bundle`, this is the proof and binding signature. - pub fn authorization(&self) -> &T { + pub fn authorization(&self) -> &A { &self.authorization } /// Construct a new bundle by applying a transformation that might fail - /// to the value balance. - pub fn try_map_value_balance Result>( + /// to the value balance and balances of assets to burn. + pub fn try_map_value_balance Result>( self, f: F, - ) -> Result, E> { + ) -> Result, E> { Ok(Bundle { actions: self.actions, flags: self.flags, value_balance: f(self.value_balance)?, + burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: self.authorization, }) } @@ -250,9 +315,9 @@ impl Bundle { pub fn map_authorization( self, context: &mut R, - mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> U::SpendAuth, - step: impl FnOnce(&mut R, T) -> U, - ) -> Bundle { + mut spend_auth: impl FnMut(&mut R, &A, A::SpendAuth) -> U::SpendAuth, + step: impl FnOnce(&mut R, A) -> U, + ) -> Bundle { let authorization = self.authorization; Bundle { actions: self @@ -260,7 +325,9 @@ impl Bundle { .map(|a| a.map(|a_auth| spend_auth(context, &authorization, a_auth))), flags: self.flags, value_balance: self.value_balance, + burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: step(context, authorization), } } @@ -269,9 +336,9 @@ impl Bundle { pub fn try_map_authorization( self, context: &mut R, - mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> Result, - step: impl FnOnce(&mut R, T) -> Result, - ) -> Result, E> { + mut spend_auth: impl FnMut(&mut R, &A, A::SpendAuth) -> Result, + step: impl FnOnce(&mut R, A) -> Result, + ) -> Result, E> { let authorization = self.authorization; let new_actions = self .actions @@ -283,7 +350,9 @@ impl Bundle { actions: NonEmpty::from_vec(new_actions).unwrap(), flags: self.flags, value_balance: self.value_balance, + burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: step(context, authorization)?, }) } @@ -383,7 +452,29 @@ impl Bundle { } } -impl> Bundle { +pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into, FL: 'a + OrchardFlavor>( + actions: impl IntoIterator>, + value_balance: V, + burn: impl Iterator, +) -> redpallas::VerificationKey { + (actions + .into_iter() + .map(|a| a.cv_net()) + .sum::() + - ValueCommitment::derive( + ValueSum::from_raw(value_balance.into()), + ValueCommitTrapdoor::zero(), + AssetBase::native(), + ) + - burn + .map(|(asset, value)| { + ValueCommitment::derive(ValueSum::from(value), ValueCommitTrapdoor::zero(), asset) + }) + .sum::()) + .into_bvk() +} + +impl, FL: OrchardFlavor> Bundle { /// Computes a commitment to the effects of this bundle, suitable for inclusion within /// a transaction ID. pub fn commitment(&self) -> BundleCommitment { @@ -395,17 +486,7 @@ impl> Bundle { /// This can be used to validate the [`Authorized::binding_signature`] returned from /// [`Bundle::authorization`]. pub fn binding_validating_key(&self) -> redpallas::VerificationKey { - // https://p.z.cash/TCR:bad-txns-orchard-binding-signature-invalid?partial - (self - .actions - .iter() - .map(|a| a.cv_net()) - .sum::() - - ValueCommitment::derive( - ValueSum::from_raw(self.value_balance.into()), - ValueCommitTrapdoor::zero(), - )) - .into_bvk() + derive_bvk(&self.actions, self.value_balance, self.burn.iter().cloned()) } } @@ -440,7 +521,7 @@ impl Authorized { } } -impl Bundle { +impl Bundle { /// Computes a commitment to the authorizing data within for this bundle. /// /// This together with `Bundle::commitment` bind the entire bundle. @@ -456,7 +537,7 @@ impl Bundle { } } -impl DynamicUsage for Bundle { +impl DynamicUsage for Bundle { fn dynamic_usage(&self) -> usize { self.actions.dynamic_usage() + self.value_balance.dynamic_usage() @@ -521,7 +602,11 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; - pub use crate::action::testing::{arb_action, arb_unauthorized_action}; + pub use crate::action::testing::ActionArb; + use crate::domain::OrchardDomainCommon; + use crate::note::asset_base::testing::arb_zsa_asset_base; + use crate::note::AssetBase; + use crate::value::testing::arb_note_value; /// Marker for an unauthorized bundle with no proofs or signatures. #[derive(Debug)] @@ -531,127 +616,151 @@ pub mod testing { type SpendAuth = (); } - /// Generate an unauthorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. - pub fn arb_unauthorized_action_n( - n_actions: usize, - flags: Flags, - ) -> impl Strategy)> { - let spend_value_gen = if flags.spends_enabled { - Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) - } else { - Strategy::boxed(Just(NoteValue::zero())) - }; + /// `BundleArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol variations + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct BundleArb { + phantom: std::marker::PhantomData, + } - spend_value_gen.prop_flat_map(move |spend_value| { - let output_value_gen = if flags.outputs_enabled { + impl BundleArb { + /// Generate an unauthorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. + pub fn arb_unauthorized_action_n( + n_actions: usize, + flags: Flags, + ) -> impl Strategy)> { + let spend_value_gen = if flags.spends_enabled { Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) } else { Strategy::boxed(Just(NoteValue::zero())) }; - output_value_gen.prop_flat_map(move |output_value| { - arb_unauthorized_action(spend_value, output_value) - .prop_map(move |a| (spend_value - output_value, a)) - }) - }) - } + spend_value_gen.prop_flat_map(move |spend_value| { + let output_value_gen = if flags.outputs_enabled { + Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) + } else { + Strategy::boxed(Just(NoteValue::zero())) + }; - /// Generate an authorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. - pub fn arb_action_n( - n_actions: usize, - flags: Flags, - ) -> impl Strategy>)> { - let spend_value_gen = if flags.spends_enabled { - Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) - } else { - Strategy::boxed(Just(NoteValue::zero())) - }; + output_value_gen.prop_flat_map(move |output_value| { + ActionArb::arb_unauthorized_action(spend_value, output_value) + .prop_map(move |a| (spend_value - output_value, a)) + }) + }) + } - spend_value_gen.prop_flat_map(move |spend_value| { - let output_value_gen = if flags.outputs_enabled { + /// Generate an authorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. + pub fn arb_action_n( + n_actions: usize, + flags: Flags, + ) -> impl Strategy, D>)> { + let spend_value_gen = if flags.spends_enabled { Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) } else { Strategy::boxed(Just(NoteValue::zero())) }; - output_value_gen.prop_flat_map(move |output_value| { - arb_action(spend_value, output_value) - .prop_map(move |a| (spend_value - output_value, a)) + spend_value_gen.prop_flat_map(move |spend_value| { + let output_value_gen = if flags.outputs_enabled { + Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) + } else { + Strategy::boxed(Just(NoteValue::zero())) + }; + + output_value_gen.prop_flat_map(move |output_value| { + ActionArb::arb_action(spend_value, output_value) + .prop_map(move |a| (spend_value - output_value, a)) + }) }) - }) - } + } - prop_compose! { - /// Create an arbitrary set of flags. - pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY) -> Flags { - Flags::from_parts(spends_enabled, outputs_enabled) + prop_compose! { + /// Create an arbitrary vector of assets to burn. + pub fn arb_asset_to_burn() + ( + asset_base in arb_zsa_asset_base(), + value in arb_note_value() + ) -> (AssetBase, NoteValue) { + (asset_base, value) + } } - } - prop_compose! { - fn arb_base()(bytes in prop::array::uniform32(0u8..)) -> pallas::Base { - // Instead of rejecting out-of-range bytes, let's reduce them. - let mut buf = [0; 64]; - buf[..32].copy_from_slice(&bytes); - pallas::Base::from_uniform_bytes(&buf) + prop_compose! { + /// Create an arbitrary set of flags. + pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY, zsa_enabled in prop::bool::ANY) -> Flags { + Flags::from_parts(spends_enabled, outputs_enabled, zsa_enabled) + } } - } - prop_compose! { - /// Generate an arbitrary unauthorized bundle. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_bundle`] - pub fn arb_unauthorized_bundle(n_actions: usize) - ( - flags in arb_flags(), - ) - ( - acts in vec(arb_unauthorized_action_n(n_actions, flags), n_actions), - anchor in arb_base().prop_map(Anchor::from), - flags in Just(flags) - ) -> Bundle { - let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); - - Bundle::from_parts( - NonEmpty::from_vec(actions).unwrap(), - flags, - balances.into_iter().sum::>().unwrap(), - anchor, - Unauthorized + prop_compose! { + fn arb_base()(bytes in prop::array::uniform32(0u8..)) -> pallas::Base { + // Instead of rejecting out-of-range bytes, let's reduce them. + let mut buf = [0; 64]; + buf[..32].copy_from_slice(&bytes); + pallas::Base::from_uniform_bytes(&buf) + } + } + + prop_compose! { + /// Generate an arbitrary unauthorized bundle. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_bundle`] + pub fn arb_unauthorized_bundle(n_actions: usize) + ( + flags in Self::arb_flags(), ) + ( + acts in vec(Self::arb_unauthorized_action_n(n_actions, flags), n_actions), + anchor in Self::arb_base().prop_map(Anchor::from), + flags in Just(flags), + burn in vec(Self::arb_asset_to_burn(), 1usize..10) + ) -> Bundle { + let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); + + Bundle::from_parts( + NonEmpty::from_vec(actions).unwrap(), + flags, + balances.into_iter().sum::>().unwrap(), + burn, + anchor, + Unauthorized, + ) + } } - } - prop_compose! { - /// Generate an arbitrary bundle with fake authorization data. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_bundle`] - pub fn arb_bundle(n_actions: usize) - ( - flags in arb_flags(), - ) - ( - acts in vec(arb_action_n(n_actions, flags), n_actions), - anchor in arb_base().prop_map(Anchor::from), - sk in arb_binding_signing_key(), - rng_seed in prop::array::uniform32(prop::num::u8::ANY), - fake_proof in vec(prop::num::u8::ANY, 1973), - fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - flags in Just(flags) - ) -> Bundle { - let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); - let rng = StdRng::from_seed(rng_seed); - - Bundle::from_parts( - NonEmpty::from_vec(actions).unwrap(), - flags, - balances.into_iter().sum::>().unwrap(), - anchor, - Authorized { - proof: Proof::new(fake_proof), - binding_signature: sk.sign(rng, &fake_sighash), - } + prop_compose! { + /// Generate an arbitrary bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_bundle`] + pub fn arb_bundle(n_actions: usize) + ( + flags in Self::arb_flags(), ) + ( + acts in vec(Self::arb_action_n(n_actions, flags), n_actions), + anchor in Self::arb_base().prop_map(Anchor::from), + sk in arb_binding_signing_key(), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + fake_proof in vec(prop::num::u8::ANY, 1973), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY), + flags in Just(flags), + burn in vec(Self::arb_asset_to_burn(), 1usize..10) + ) -> Bundle { + let (balances, actions): (Vec, Vec, >) = acts.into_iter().unzip(); + let rng = StdRng::from_seed(rng_seed); + + Bundle::from_parts( + NonEmpty::from_vec(actions).unwrap(), + flags, + balances.into_iter().sum::>().unwrap(), + burn, + anchor, + Authorized { + proof: Proof::new(fake_proof), + binding_signature: sk.sign(rng, &fake_sighash), + }, + ) + } } } } diff --git a/src/bundle/batch.rs b/src/bundle/batch.rs index 6626b9162..cc9811c18 100644 --- a/src/bundle/batch.rs +++ b/src/bundle/batch.rs @@ -4,8 +4,10 @@ use rand::{CryptoRng, RngCore}; use tracing::debug; use super::{Authorized, Bundle}; + use crate::{ circuit::VerifyingKey, + orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, }; @@ -35,9 +37,9 @@ impl BatchValidator { } /// Adds the proof and RedPallas signatures from the given bundle to the validator. - pub fn add_bundle>( + pub fn add_bundle, FL: OrchardFlavor>( &mut self, - bundle: &Bundle, + bundle: &Bundle, sighash: [u8; 32], ) { for action in bundle.actions().iter() { diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs new file mode 100644 index 000000000..d6388f10c --- /dev/null +++ b/src/bundle/burn_validation.rs @@ -0,0 +1,147 @@ +//! Validating burn operations on asset bundles. +//! +//! The module provides a function `validate_bundle_burn` that can be used to validate the burn values for the bundle. +//! +use std::{collections::HashSet, fmt}; + +use crate::{note::AssetBase, value::NoteValue}; + +/// Possible errors that can occur during bundle burn validation. +#[derive(Debug)] +#[cfg_attr(test, derive(PartialEq, Eq))] +pub enum BurnError { + /// Encountered a duplicate asset to burn. + DuplicateAsset, + /// Cannot burn a native asset. + NativeAsset, + /// Cannot burn an asset with a zero value. + ZeroAmount, +} + +/// Validates burn for a bundle by ensuring each asset is unique, non-native, and has a non-zero value. +/// +/// Each burn element is represented as a tuple of `AssetBase` and `NoteValue` (value for the burn). +/// +/// # Arguments +/// +/// * `burn` - A vector of assets, where each asset is represented as a tuple of `AssetBase` and `NoteValue` (value the burn). +/// +/// # Errors +/// +/// Returns a `BurnError` if: +/// * Any asset in the `burn` vector is native (`BurnError::NativeAsset`). +/// * Any asset in the `burn` vector has a zero value (`BurnError::ZeroAmount`). +/// * Any asset in the `burn` vector is not unique (`BurnError::DuplicateAsset`). +pub fn validate_bundle_burn(burn: &[(AssetBase, NoteValue)]) -> Result<(), BurnError> { + let mut burn_set = HashSet::new(); + + for (asset, value) in burn { + if asset.is_native().into() { + return Err(BurnError::NativeAsset); + } + if value.inner() == 0 { + return Err(BurnError::ZeroAmount); + } + if !burn_set.insert(*asset) { + return Err(BurnError::DuplicateAsset); + } + } + + Ok(()) +} + +impl fmt::Display for BurnError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + BurnError::DuplicateAsset => write!(f, "Encountered a duplicate asset to burn."), + BurnError::NativeAsset => write!(f, "Cannot burn a native asset."), + BurnError::ZeroAmount => { + write!(f, "Cannot burn an asset with a zero value.") + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::value::NoteValue; + + use super::*; + + /// Creates an item of bundle burn list for a given asset description and value. + /// + /// This function is deterministic and guarantees that each call with the same parameters + /// will return the same result. It achieves determinism by using a static `IssuanceAuthorizingKey`. + /// + /// # Arguments + /// + /// * `asset_desc` - The asset description string. + /// * `value` - The value for the burn. + /// + /// # Returns + /// + /// A tuple `(AssetBase, Amount)` representing the burn list item. + /// + pub fn get_burn_tuple(asset_desc: &[u8], value: u64) -> (AssetBase, NoteValue) { + use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; + + let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); + + ( + AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc), + NoteValue::from_raw(value), + ) + } + + #[test] + fn validate_bundle_burn_success() { + let bundle_burn = vec![ + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 2", 20), + get_burn_tuple(b"Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert!(result.is_ok()); + } + + #[test] + fn validate_bundle_burn_duplicate_asset() { + let bundle_burn = vec![ + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 1", 20), + get_burn_tuple(b"Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::DuplicateAsset)); + } + + #[test] + fn validate_bundle_burn_native_asset() { + let bundle_burn = vec![ + get_burn_tuple(b"Asset 1", 10), + (AssetBase::native(), NoteValue::from_raw(20)), + get_burn_tuple(b"Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::NativeAsset)); + } + + #[test] + fn validate_bundle_burn_zero_value() { + let bundle_burn = vec![ + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 2", 0), + get_burn_tuple(b"Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::ZeroAmount)); + } +} diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index ef440a272..b25aa375d 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -2,60 +2,49 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; -use crate::bundle::{Authorization, Authorized, Bundle}; +use crate::{ + bundle::{Authorization, Authorized, Bundle}, + domain::OrchardDomainCommon, + issuance::{IssueAuth, IssueBundle, Signed}, +}; -const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; -const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash"; -const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; -const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; -const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +pub(crate) const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; +pub(crate) const ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActGHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxIdOrcActCHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxIdOrcActNHash"; +pub(crate) const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash"; +pub(crate) const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +pub(crate) const ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxAuthOrcAGHash"; -fn hasher(personal: &[u8; 16]) -> State { +const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION: &[u8; 16] = b"ZTxAuthZSAOrHash"; + +pub(crate) fn hasher(personal: &[u8; 16]) -> State { Params::new().hash_length(32).personal(personal).to_state() } -/// Write disjoint parts of each Orchard shielded action as 3 separate hashes: -/// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION -/// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized -/// with ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION -/// * \[(cv, rk, enc_ciphertext\[564..\], out_ciphertext)*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION -/// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244] -/// -/// Then, hash these together along with (flags, value_balance_orchard, anchor_orchard), -/// personalized with ZCASH_ORCHARD_ACTIONS_HASH_PERSONALIZATION +/// Evaluate `orchard_digest` for the bundle as defined in +/// [ZIP-244: Transaction Identifier Non-Malleability][zip244] +/// for OrchardVanilla and as defined in +/// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] +/// for OrchardZSA /// /// [zip244]: https://zips.z.cash/zip-0244 -pub(crate) fn hash_bundle_txid_data>( - bundle: &Bundle, +/// [zip226]: https://zips.z.cash/zip-0226 +pub(crate) fn hash_bundle_txid_data< + A: Authorization, + V: Copy + Into, + D: OrchardDomainCommon, +>( + bundle: &Bundle, ) -> Blake2bHash { - let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); - let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION); - let mut mh = hasher(ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION); - let mut nh = hasher(ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION); - - for action in bundle.actions().iter() { - ch.update(&action.nullifier().to_bytes()); - ch.update(&action.cmx().to_bytes()); - ch.update(&action.encrypted_note().epk_bytes); - ch.update(&action.encrypted_note().enc_ciphertext[..52]); - - mh.update(&action.encrypted_note().enc_ciphertext[52..564]); - - nh.update(&action.cv_net().to_bytes()); - nh.update(&<[u8; 32]>::from(action.rk())); - nh.update(&action.encrypted_note().enc_ciphertext[564..]); - nh.update(&action.encrypted_note().out_ciphertext); - } - - h.update(ch.finalize().as_bytes()); - h.update(mh.finalize().as_bytes()); - h.update(nh.finalize().as_bytes()); - h.update(&[bundle.flags().to_byte()]); - h.update(&(*bundle.value_balance()).into().to_le_bytes()); - h.update(&bundle.anchor().to_bytes()); - h.finalize() + D::hash_bundle_txid_data(bundle) } /// Construct the commitment for the absent bundle as defined in @@ -71,16 +60,10 @@ pub fn hash_bundle_txid_empty() -> Blake2bHash { /// Identifier Non-Malleability][zip244] /// /// [zip244]: https://zips.z.cash/zip-0244 -pub(crate) fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { - let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); - h.update(bundle.authorization().proof().as_ref()); - for action in bundle.actions().iter() { - h.update(&<[u8; 64]>::from(action.authorization())); - } - h.update(&<[u8; 64]>::from( - bundle.authorization().binding_signature(), - )); - h.finalize() +pub(crate) fn hash_bundle_auth_data( + bundle: &Bundle, +) -> Blake2bHash { + D::hash_bundle_auth_data(bundle) } /// Construct the commitment for an absent bundle as defined in @@ -90,3 +73,162 @@ pub(crate) fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2 pub fn hash_bundle_auth_empty() -> Blake2bHash { hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION).finalize() } + +/// Construct the commitment for an absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://zips.z.cash/zip-0227 +pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize() +} + +/// Construct the commitment for an absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://zips.z.cash/zip-0227 +pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() +} + +/// Construct the commitment for the issue bundle +pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); + let mut ia = hasher(ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION); + + for action in bundle.actions() { + let mut ind = hasher(ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION); + for note in action.notes().iter() { + ind.update(¬e.recipient().to_raw_address_bytes()); + ind.update(¬e.value().to_bytes()); + ind.update(¬e.asset().to_bytes()); + ind.update(¬e.rho().to_bytes()); + ind.update(note.rseed().as_bytes()); + } + ia.update(ind.finalize().as_bytes()); + ia.update(action.asset_desc()); + ia.update(&[u8::from(action.is_finalized())]); + } + h.update(ia.finalize().as_bytes()); + h.update(&bundle.ik().to_bytes()); + h.finalize() +} + +/// Construct the commitment to the authorizing data of an +/// authorized issue bundle +pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION); + h.update(&<[u8; 64]>::from(bundle.authorization().signature())); + h.finalize() +} + +#[cfg(test)] +mod tests { + use crate::{ + builder::{Builder, BundleType, UnauthorizedBundle}, + bundle::{ + commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, + Authorized, Bundle, + }, + circuit::ProvingKey, + keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, + value::NoteValue, + Anchor, + }; + use rand::{rngs::StdRng, SeedableRng}; + + fn generate_bundle(bundle_type: BundleType) -> UnauthorizedBundle { + let rng = StdRng::seed_from_u64(5); + + let sk = SpendingKey::from_bytes([7; 32]).unwrap(); + let recipient = FullViewingKey::from(&sk).address_at(0u32, Scope::External); + + let mut builder = Builder::new(bundle_type, Anchor::from_bytes([0; 32]).unwrap()); + builder + .add_output( + None, + recipient, + NoteValue::from_raw(10), + AssetBase::native(), + None, + ) + .unwrap(); + + builder + .add_output( + None, + recipient, + NoteValue::from_raw(20), + AssetBase::native(), + None, + ) + .unwrap(); + + builder.build::(rng).unwrap().0 + } + + /// Verify that the hash for an Orchard Vanilla bundle matches a fixed reference value + /// to ensure consistency. + #[test] + fn test_hash_bundle_txid_data_for_orchard_vanilla() { + let bundle = generate_bundle::(BundleType::DEFAULT_VANILLA); + let sighash = hash_bundle_txid_data(&bundle); + assert_eq!( + sighash.to_hex().as_str(), + // Bundle hash for Orchard (vanilla) generated using + // Zcash/Orchard commit: 23a167e3972632586dc628ddbdd69d156dfd607b + "cd6f8156a54473d411c738e781b4d601363990688a926a3335145575003bf4b8" + ); + } + + /// Verify that the hash for an OrchardZSA bundle matches a fixed reference value + /// to ensure consistency. + #[test] + fn test_hash_bundle_txid_data_for_orchard_zsa() { + let bundle = generate_bundle::(BundleType::DEFAULT_ZSA); + let sighash = hash_bundle_txid_data(&bundle); + assert_eq!( + sighash.to_hex().as_str(), + "43cfaab1ffcd8d4752e5e7479fd619c769e3ab459b6f10bbba80533608f546b0" + ); + } + + fn generate_auth_bundle( + bundle_type: BundleType, + ) -> Bundle { + let mut rng = StdRng::seed_from_u64(6); + let pk = ProvingKey::build::(); + let bundle = generate_bundle(bundle_type) + .create_proof(&pk, &mut rng) + .unwrap(); + let sighash = bundle.commitment().into(); + bundle.prepare(rng, sighash).finalize().unwrap() + } + + /// Verify that the authorizing data commitment for an Orchard Vanilla bundle matches a fixed + /// reference value to ensure consistency. + #[test] + fn test_hash_bundle_auth_data_for_orchard_vanilla() { + let bundle = generate_auth_bundle::(BundleType::DEFAULT_VANILLA); + let orchard_auth_digest = hash_bundle_auth_data(&bundle); + assert_eq!( + orchard_auth_digest.to_hex().as_str(), + // Bundle hash for Orchard (vanilla) generated using + // Zcash/Orchard commit: 23a167e3972632586dc628ddbdd69d156dfd607b + "2cd424654d8cb770c8dbdf253b6829e25fc70b40157048fd7c6c19f9a9c61f76" + ); + } + + /// Verify that the authorizing data commitment for an OrchardZSA bundle matches a fixed + /// reference value to ensure consistency. + #[test] + fn test_hash_bundle_auth_data_for_orchard_zsa() { + let bundle = generate_auth_bundle::(BundleType::DEFAULT_ZSA); + let orchard_auth_digest = hash_bundle_auth_data(&bundle); + assert_eq!( + orchard_auth_digest.to_hex().as_str(), + "c765769582c598930b2825224d5d9246196954fe7cbd3a2be9afa3c542c06387" + ); + } +} diff --git a/src/circuit.rs b/src/circuit.rs index 567b60658..65ce158ef 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,34 +1,36 @@ //! The Orchard Action circuit implementation. +//! +//! This module defines the common structures, traits and implementations for the +//! Orchard Action circuit, supporting both the standard ("Vanilla") and ZSA variations. use core::fmt; use group::{Curve, GroupEncoding}; +use halo2_gadgets::{ + ecc::chip::EccConfig, + poseidon::Pow5Config as PoseidonConfig, + sinsemilla::{chip::SinsemillaConfig, merkle::chip::MerkleConfig}, + utilities::lookup_range_check::PallasLookupRangeCheck, +}; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, plonk::{ - self, Advice, BatchVerifier, Column, Constraints, Expression, Instance as InstanceColumn, - Selector, SingleVerifier, + self, Advice, BatchVerifier, Column, Instance as InstanceColumn, Selector, SingleVerifier, }, - poly::Rotation, transcript::{Blake2bRead, Blake2bWrite}, }; use memuse::DynamicUsage; use pasta_curves::{arithmetic::CurveAffine, pallas, vesta}; use rand::RngCore; -use self::{ - commit_ivk::{CommitIvkChip, CommitIvkConfig}, - gadget::{ - add_chip::{AddChip, AddConfig}, - assign_free_advice, - }, - note_commit::{NoteCommitChip, NoteCommitConfig}, -}; use crate::{ builder::SpendInfo, + bundle::Flags, + circuit::{ + commit_ivk::CommitIvkConfig, gadget::add_chip::AddConfig, note_commit::NoteCommitConfig, + }, constants::{ - OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - MERKLE_DEPTH_ORCHARD, + OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, MERKLE_DEPTH_ORCHARD, }, keys::{ CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey, @@ -36,32 +38,23 @@ use crate::{ note::{ commitment::{NoteCommitTrapdoor, NoteCommitment}, nullifier::Nullifier, - ExtractedNoteCommitment, Note, Rho, + AssetBase, ExtractedNoteCommitment, Note, Rho, }, primitives::redpallas::{SpendAuth, VerificationKey}, spec::NonIdentityPallasPoint, tree::{Anchor, MerkleHashOrchard}, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, }; -use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarFixedShort, ScalarVar, - }, - poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, - sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - merkle::{ - chip::{MerkleChip, MerkleConfig}, - MerklePath, - }, - }, - utilities::lookup_range_check::LookupRangeCheckConfig, -}; -mod commit_ivk; -pub mod gadget; -mod note_commit; +mod circuit_vanilla; +mod circuit_zsa; + +pub(in crate::circuit) mod commit_ivk; +pub(in crate::circuit) mod derive_nullifier; +pub(in crate::circuit) mod gadget; +pub(in crate::circuit) mod note_commit; +pub(in crate::circuit) mod orchard_sinsemilla_chip; +pub(in crate::circuit) mod value_commit_orchard; /// Size of the Orchard circuit. const K: u32 = 11; @@ -76,30 +69,79 @@ const RK_Y: usize = 5; const CMX: usize = 6; const ENABLE_SPEND: usize = 7; const ENABLE_OUTPUT: usize = 8; +const ENABLE_ZSA: usize = 9; /// Configuration needed to use the Orchard Action circuit. #[derive(Clone, Debug)] -pub struct Config { +pub struct Config { primary: Column, q_orchard: Selector, advices: [Column; 10], add_config: AddConfig, - ecc_config: EccConfig, + ecc_config: EccConfig, poseidon_config: PoseidonConfig, - merkle_config_1: MerkleConfig, - merkle_config_2: MerkleConfig, + merkle_config_1: + MerkleConfig, + merkle_config_2: + MerkleConfig, sinsemilla_config_1: - SinsemillaConfig, + SinsemillaConfig, sinsemilla_config_2: - SinsemillaConfig, + SinsemillaConfig, commit_ivk_config: CommitIvkConfig, - old_note_commit_config: NoteCommitConfig, - new_note_commit_config: NoteCommitConfig, + old_note_commit_config: NoteCommitConfig, + new_note_commit_config: NoteCommitConfig, +} + +/// The `OrchardCircuit` trait defines an interface for different implementations of the PLONK circuit +/// for the different Orchard protocol flavors (Vanilla and ZSA). It serves as a bridge between +/// plonk::Circuit interfaces and specific requirements of the Orchard protocol's variations. +pub trait OrchardCircuit: Sized + Default { + /// Substitution for Config type of plonk::Circuit trait + type Config: Clone; + + /// Wrapper for configure function of plonk::Circuit trait + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config; + + /// Wrapper for configure function of plonk::Circuit trait + fn synthesize( + circuit: &Witnesses, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), plonk::Error>; +} + +impl plonk::Circuit for Circuit { + type Config = C::Config; + type FloorPlanner = floor_planner::V1; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + C::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + C::synthesize(&self.witnesses, config, layouter) + } } /// The Orchard Action circuit. #[derive(Clone, Debug, Default)] -pub struct Circuit { +pub struct Circuit { + pub(crate) witnesses: Witnesses, + pub(crate) phantom: std::marker::PhantomData, +} + +/// The Orchard Action witnesses +#[derive(Clone, Debug, Default)] +pub struct Witnesses { pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, pub(crate) pos: Value, pub(crate) g_d_old: Value, @@ -109,6 +151,7 @@ pub struct Circuit { pub(crate) psi_old: Value, pub(crate) rcm_old: Value, pub(crate) cm_old: Value, + pub(crate) psi_nf: Value, pub(crate) alpha: Value, pub(crate) ak: Value, pub(crate) nk: Value, @@ -119,9 +162,11 @@ pub struct Circuit { pub(crate) psi_new: Value, pub(crate) rcm_new: Value, pub(crate) rcv: Value, + pub(crate) asset: Value, + pub(crate) split_flag: Value, } -impl Circuit { +impl Witnesses { /// This constructor is public to enable creation of custom builders. /// If you are not creating a custom builder, use [`Builder`] to compose /// and authorize a transaction. @@ -142,7 +187,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Option { + ) -> Option { (Rho::from_nf_old(spend.note.nullifier(&spend.fvk)) == output_note.rho()) .then(|| Self::from_action_context_unchecked(spend, output_note, alpha, rcv)) } @@ -152,17 +197,20 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Circuit { + ) -> Self { let sender_address = spend.note.recipient(); let rho_old = spend.note.rho(); let psi_old = spend.note.rseed().psi(&rho_old); let rcm_old = spend.note.rseed().rcm(&rho_old); + let nf_rseed = spend.note.rseed_split_note().unwrap_or(*spend.note.rseed()); + let psi_nf = nf_rseed.psi(&rho_old); + let rho_new = output_note.rho(); let psi_new = output_note.rseed().psi(&rho_new); let rcm_new = output_note.rseed().rcm(&rho_new); - Circuit { + Witnesses { path: Value::known(spend.merkle_path.auth_path()), pos: Value::known(spend.merkle_path.position()), g_d_old: Value::known(sender_address.g_d()), @@ -172,6 +220,7 @@ impl Circuit { psi_old: Value::known(psi_old), rcm_old: Value::known(rcm_old), cm_old: Value::known(spend.note.commitment()), + psi_nf: Value::known(psi_nf), alpha: Value::known(alpha), ak: Value::known(spend.fvk.clone().into()), nk: Value::known(*spend.fvk.nk()), @@ -182,577 +231,12 @@ impl Circuit { psi_new: Value::known(psi_new), rcm_new: Value::known(rcm_new), rcv: Value::known(rcv), + asset: Value::known(spend.note.asset()), + split_flag: Value::known(spend.split_flag), } } } -impl plonk::Circuit for Circuit { - type Config = Config; - type FloorPlanner = floor_planner::V1; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - // Advice columns used in the Orchard circuit. - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Constrain v_old - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Either v_old = 0, or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). - // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). - // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). - let q_orchard = meta.selector(); - meta.create_gate("Orchard circuit checks", |meta| { - let q_orchard = meta.query_selector(q_orchard); - let v_old = meta.query_advice(advices[0], Rotation::cur()); - let v_new = meta.query_advice(advices[1], Rotation::cur()); - let magnitude = meta.query_advice(advices[2], Rotation::cur()); - let sign = meta.query_advice(advices[3], Rotation::cur()); - - let root = meta.query_advice(advices[4], Rotation::cur()); - let anchor = meta.query_advice(advices[5], Rotation::cur()); - - let enable_spends = meta.query_advice(advices[6], Rotation::cur()); - let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); - - let one = Expression::Constant(pallas::Base::one()); - - Constraints::with_selector( - q_orchard, - [ - ( - "v_old - v_new = magnitude * sign", - v_old.clone() - v_new.clone() - magnitude * sign, - ), - ( - "Either v_old = 0, or root = anchor", - v_old.clone() * (root - anchor), - ), - ( - "v_old = 0 or enable_spends = 1", - v_old * (one.clone() - enable_spends), - ), - ( - "v_new = 0 or enable_outputs = 1", - v_new * (one - enable_outputs), - ), - ], - ) - }); - - // Addition of two field elements. - let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); - - // Fixed columns for the Sinsemilla generator lookup table - let table_idx = meta.lookup_table_column(); - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - // Instance column used for public inputs - let primary = meta.instance_column(); - meta.enable_equality(primary); - - // Permutation over all advice columns. - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - // Poseidon requires four advice columns, while ECC incomplete addition requires - // six, so we could choose to configure them in parallel. However, we only use a - // single Poseidon invocation, and we have the rows to accommodate it serially. - // Instead, we reduce the proof size by sharing fixed columns between the ECC and - // Poseidon chips. - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); - let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); - - // Also use the first Lagrange coefficient column for loading global constants. - // It's free real estate :) - meta.enable_constant(lagrange_coeffs[0]); - - // We have a lot of free space in the right-most advice columns; use one of them - // for all of our range checks. - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - - // Configuration for curve point operations. - // This uses 10 advice columns and spans the whole circuit. - let ecc_config = - EccChip::::configure(meta, advices, lagrange_coeffs, range_check); - - // Configuration for the Poseidon hash. - let poseidon_config = PoseidonChip::configure::( - meta, - // We place the state columns after the partial_sbox column so that the - // pad-and-add region can be laid out more efficiently. - advices[6..9].try_into().unwrap(), - advices[5], - rc_a, - rc_b, - ); - - // Configuration for a Sinsemilla hash instantiation and a - // Merkle hash instantiation using this Sinsemilla instance. - // Since the Sinsemilla config uses only 5 advice columns, - // we can fit two instances side-by-side. - let (sinsemilla_config_1, merkle_config_1) = { - let sinsemilla_config_1 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[6], - lagrange_coeffs[0], - lookup, - range_check, - ); - let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); - - (sinsemilla_config_1, merkle_config_1) - }; - - // Configuration for a Sinsemilla hash instantiation and a - // Merkle hash instantiation using this Sinsemilla instance. - // Since the Sinsemilla config uses only 5 advice columns, - // we can fit two instances side-by-side. - let (sinsemilla_config_2, merkle_config_2) = { - let sinsemilla_config_2 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - lagrange_coeffs[1], - lookup, - range_check, - ); - let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); - - (sinsemilla_config_2, merkle_config_2) - }; - - // Configuration to handle decomposition and canonicity checking - // for CommitIvk. - let commit_ivk_config = CommitIvkChip::configure(meta, advices); - - // Configuration to handle decomposition and canonicity checking - // for NoteCommit_old. - let old_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); - - // Configuration to handle decomposition and canonicity checking - // for NoteCommit_new. - let new_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); - - Config { - primary, - q_orchard, - advices, - add_config, - ecc_config, - poseidon_config, - merkle_config_1, - merkle_config_2, - sinsemilla_config_1, - sinsemilla_config_2, - commit_ivk_config, - old_note_commit_config, - new_note_commit_config, - } - } - - #[allow(non_snake_case)] - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), plonk::Error> { - // Load the Sinsemilla generator lookup table used by the whole circuit. - SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; - - // Construct the ECC chip. - let ecc_chip = config.ecc_chip(); - - // Witness private inputs that are used across multiple checks. - let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = { - // Witness psi_old - let psi_old = assign_free_advice( - layouter.namespace(|| "witness psi_old"), - config.advices[0], - self.psi_old, - )?; - - // Witness rho_old - let rho_old = assign_free_advice( - layouter.namespace(|| "witness rho_old"), - config.advices[0], - self.rho_old.map(|rho| rho.into_inner()), - )?; - - // Witness cm_old - let cm_old = Point::new( - ecc_chip.clone(), - layouter.namespace(|| "cm_old"), - self.cm_old.as_ref().map(|cm| cm.inner().to_affine()), - )?; - - // Witness g_d_old - let g_d_old = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "gd_old"), - self.g_d_old.as_ref().map(|gd| gd.to_affine()), - )?; - - // Witness ak_P. - let ak_P: Value = self.ak.as_ref().map(|ak| ak.into()); - let ak_P = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness ak_P"), - ak_P.map(|ak_P| ak_P.to_affine()), - )?; - - // Witness nk. - let nk = assign_free_advice( - layouter.namespace(|| "witness nk"), - config.advices[0], - self.nk.map(|nk| nk.inner()), - )?; - - // Witness v_old. - let v_old = assign_free_advice( - layouter.namespace(|| "witness v_old"), - config.advices[0], - self.v_old, - )?; - - // Witness v_new. - let v_new = assign_free_advice( - layouter.namespace(|| "witness v_new"), - config.advices[0], - self.v_new, - )?; - - (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) - }; - - // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). - let root = { - let path = self - .path - .map(|typed_path| typed_path.map(|node| node.inner())); - let merkle_inputs = MerklePath::construct( - [config.merkle_chip_1(), config.merkle_chip_2()], - OrchardHashDomains::MerkleCrh, - self.pos, - path, - ); - let leaf = cm_old.extract_p().inner().clone(); - merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? - }; - - // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - let v_net_magnitude_sign = { - // Witness the magnitude and sign of v_net = v_old - v_new - let v_net_magnitude_sign = { - let v_net = self.v_old - self.v_new; - let magnitude_sign = v_net.map(|v_net| { - let (magnitude, sign) = v_net.magnitude_sign(); - - ( - // magnitude is guaranteed to be an unsigned 64-bit value. - // Therefore, we can move it into the base field. - pallas::Base::from(magnitude), - match sign { - crate::value::Sign::Positive => pallas::Base::one(), - crate::value::Sign::Negative => -pallas::Base::one(), - }, - ) - }); - - let magnitude = assign_free_advice( - layouter.namespace(|| "v_net magnitude"), - config.advices[9], - magnitude_sign.map(|m_s| m_s.0), - )?; - let sign = assign_free_advice( - layouter.namespace(|| "v_net sign"), - config.advices[9], - magnitude_sign.map(|m_s| m_s.1), - )?; - (magnitude, sign) - }; - - let v_net = ScalarFixedShort::new( - ecc_chip.clone(), - layouter.namespace(|| "v_net"), - v_net_magnitude_sign.clone(), - )?; - let rcv = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rcv"), - self.rcv.as_ref().map(|rcv| rcv.inner()), - )?; - - let cv_net = gadget::value_commit_orchard( - layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), - ecc_chip.clone(), - v_net, - rcv, - )?; - - // Constrain cv_net to equal public input - layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; - layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; - - // Return the magnitude and sign so we can use them in the Orchard gate. - v_net_magnitude_sign - }; - - // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). - let nf_old = { - let nf_old = gadget::derive_nullifier( - layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), - config.poseidon_chip(), - config.add_chip(), - ecc_chip.clone(), - rho_old.clone(), - &psi_old, - &cm_old, - nk.clone(), - )?; - - // Constrain nf_old to equal public input - layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; - - nf_old - }; - - // Spend authority (https://p.z.cash/ZKS:action-spend-authority) - { - let alpha = - ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "alpha"), self.alpha)?; - - // alpha_commitment = [alpha] SpendAuthG - let (alpha_commitment, _) = { - let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; - let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); - spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? - }; - - // [alpha] SpendAuthG + ak_P - let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; - - // Constrain rk to equal public input - layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; - layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; - } - - // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). - let pk_d_old = { - let ivk = { - let ak = ak_P.extract_p().inner().clone(); - let rivk = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rivk"), - self.rivk.map(|rivk| rivk.inner()), - )?; - - gadget::commit_ivk( - config.sinsemilla_chip_1(), - ecc_chip.clone(), - config.commit_ivk_chip(), - layouter.namespace(|| "CommitIvk"), - ak, - nk, - rivk, - )? - }; - let ivk = - ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; - - // [ivk] g_d_old - // The scalar value is passed through and discarded. - let (derived_pk_d_old, _ivk) = - g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; - - // Constrain derived pk_d_old to equal witnessed pk_d_old - // - // This equality constraint is technically superfluous, because the assigned - // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see - // an explicit connection between circuit-synthesized values, and explicit - // prover witnesses. We could get the best of both worlds with a write-on-copy - // abstraction (https://github.com/zcash/halo2/issues/334). - let pk_d_old = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d_old"), - self.pk_d_old.map(|pk_d_old| pk_d_old.inner().to_affine()), - )?; - derived_pk_d_old - .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; - - pk_d_old - }; - - // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). - { - let rcm_old = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rcm_old"), - self.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), - )?; - - // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let derived_cm_old = gadget::note_commit( - layouter.namespace(|| { - "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" - }), - config.sinsemilla_chip_1(), - config.ecc_chip(), - config.note_commit_chip_old(), - g_d_old.inner(), - pk_d_old.inner(), - v_old.clone(), - rho_old, - psi_old, - rcm_old, - )?; - - // Constrain derived cm_old to equal witnessed cm_old - derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; - } - - // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). - { - // Witness g_d_new - let g_d_new = { - let g_d_new = self.g_d_new.map(|g_d_new| g_d_new.to_affine()); - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness g_d_new_star"), - g_d_new, - )? - }; - - // Witness pk_d_new - let pk_d_new = { - let pk_d_new = self.pk_d_new.map(|pk_d_new| pk_d_new.inner().to_affine()); - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d_new"), - pk_d_new, - )? - }; - - // ρ^new = nf^old - let rho_new = nf_old.inner().clone(); - - // Witness psi_new - let psi_new = assign_free_advice( - layouter.namespace(|| "witness psi_new"), - config.advices[0], - self.psi_new, - )?; - - let rcm_new = ScalarFixed::new( - ecc_chip, - layouter.namespace(|| "rcm_new"), - self.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), - )?; - - // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let cm_new = gadget::note_commit( - layouter.namespace(|| { - "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" - }), - config.sinsemilla_chip_2(), - config.ecc_chip(), - config.note_commit_chip_new(), - g_d_new.inner(), - pk_d_new.inner(), - v_new.clone(), - rho_new, - psi_new, - rcm_new, - )?; - - let cmx = cm_new.extract_p(); - - // Constrain cmx to equal public input - layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; - } - - // Constrain the remaining Orchard circuit checks. - layouter.assign_region( - || "Orchard circuit checks", - |mut region| { - v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; - v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; - v_net_magnitude_sign.0.copy_advice( - || "v_net magnitude", - &mut region, - config.advices[2], - 0, - )?; - v_net_magnitude_sign.1.copy_advice( - || "v_net sign", - &mut region, - config.advices[3], - 0, - )?; - - root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; - region.assign_advice_from_instance( - || "pub input anchor", - config.primary, - ANCHOR, - config.advices[5], - 0, - )?; - - region.assign_advice_from_instance( - || "enable spends", - config.primary, - ENABLE_SPEND, - config.advices[6], - 0, - )?; - - region.assign_advice_from_instance( - || "enable outputs", - config.primary, - ENABLE_OUTPUT, - config.advices[7], - 0, - )?; - - config.q_orchard.enable(&mut region, 0) - }, - )?; - - Ok(()) - } -} - /// The verifying key for the Orchard Action circuit. #[derive(Debug)] pub struct VerifyingKey { @@ -762,9 +246,9 @@ pub struct VerifyingKey { impl VerifyingKey { /// Builds the verifying key. - pub fn build() -> Self { + pub fn build() -> Self { let params = halo2_proofs::poly::commitment::Params::new(K); - let circuit: Circuit = Default::default(); + let circuit: Circuit = Default::default(); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); @@ -781,9 +265,9 @@ pub struct ProvingKey { impl ProvingKey { /// Builds the proving key. - pub fn build() -> Self { + pub fn build() -> Self { let params = halo2_proofs::poly::commitment::Params::new(K); - let circuit: Circuit = Default::default(); + let circuit: Circuit = Default::default(); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); let pk = plonk::keygen_pk(¶ms, vk, &circuit).unwrap(); @@ -802,6 +286,7 @@ pub struct Instance { pub(crate) cmx: ExtractedNoteCommitment, pub(crate) enable_spend: bool, pub(crate) enable_output: bool, + pub(crate) enable_zsa: bool, } impl Instance { @@ -818,8 +303,7 @@ impl Instance { nf_old: Nullifier, rk: VerificationKey, cmx: ExtractedNoteCommitment, - enable_spend: bool, - enable_output: bool, + flags: Flags, ) -> Self { Instance { anchor, @@ -827,13 +311,14 @@ impl Instance { nf_old, rk, cmx, - enable_spend, - enable_output, + enable_spend: flags.spends_enabled(), + enable_output: flags.outputs_enabled(), + enable_zsa: flags.zsa_enabled(), } } - fn to_halo2_instance(&self) -> [[vesta::Scalar; 9]; 1] { - let mut instance = [vesta::Scalar::zero(); 9]; + fn to_halo2_instance(&self) -> [[vesta::Scalar; 10]; 1] { + let mut instance = [vesta::Scalar::zero(); 10]; instance[ANCHOR] = self.anchor.inner(); instance[CV_NET_X] = self.cv_net.x(); @@ -851,6 +336,7 @@ impl Instance { instance[CMX] = self.cmx.inner(); instance[ENABLE_SPEND] = vesta::Scalar::from(u64::from(self.enable_spend)); instance[ENABLE_OUTPUT] = vesta::Scalar::from(u64::from(self.enable_output)); + instance[ENABLE_ZSA] = vesta::Scalar::from(u64::from(self.enable_zsa)); [instance] } @@ -893,9 +379,9 @@ impl DynamicUsage for Proof { impl Proof { /// Creates a proof for the given circuits and instances. - pub fn create( + pub fn create( pk: &ProvingKey, - circuits: &[Circuit], + circuits: &[Circuit], instances: &[Instance], mut rng: impl RngCore, ) -> Result { @@ -957,258 +443,3 @@ impl Proof { Proof(bytes) } } - -#[cfg(test)] -mod tests { - use core::iter; - - use ff::Field; - use halo2_proofs::{circuit::Value, dev::MockProver}; - use pasta_curves::pallas; - use rand::{rngs::OsRng, RngCore}; - - use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; - use crate::{ - keys::SpendValidatingKey, - note::{Note, Rho}, - tree::MerklePath, - value::{ValueCommitTrapdoor, ValueCommitment}, - }; - - fn generate_circuit_instance(mut rng: R) -> (Circuit, Instance) { - let (_, fvk, spent_note) = Note::dummy(&mut rng, None); - - let sender_address = spent_note.recipient(); - let nk = *fvk.nk(); - let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); - let nf_old = spent_note.nullifier(&fvk); - let rho = Rho::from_nf_old(nf_old); - let ak: SpendValidatingKey = fvk.into(); - let alpha = pallas::Scalar::random(&mut rng); - let rk = ak.randomize(&alpha); - - let (_, _, output_note) = Note::dummy(&mut rng, Some(rho)); - let cmx = output_note.commitment().into(); - - let value = spent_note.value() - output_note.value(); - let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv.clone()); - - let path = MerklePath::dummy(&mut rng); - let anchor = path.root(spent_note.commitment().into()); - - ( - Circuit { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - }, - Instance { - anchor, - cv_net, - nf_old, - rk, - cmx, - enable_spend: true, - enable_output: true, - }, - ) - } - - // TODO: recast as a proptest - #[test] - fn round_trip() { - let mut rng = OsRng; - - let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) - .map(|()| generate_circuit_instance(&mut rng)) - .unzip(); - - let vk = VerifyingKey::build(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. - { - // panic!("{:#?}", vk.vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.vk.pinned()), - include_str!("circuit_description").replace("\r\n", "\n") - ); - } - - // Test that the proof size is as expected. - let expected_proof_size = { - let circuit_cost = - halo2_proofs::dev::CircuitCost::::measure( - K, - &circuits[0], - ); - assert_eq!(usize::from(circuit_cost.proof_size(1)), 4992); - assert_eq!(usize::from(circuit_cost.proof_size(2)), 7264); - usize::from(circuit_cost.proof_size(instances.len())) - }; - - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - assert_eq!( - MockProver::run( - K, - circuit, - instance - .to_halo2_instance() - .iter() - .map(|p| p.to_vec()) - .collect() - ) - .unwrap() - .verify(), - Ok(()) - ); - } - - let pk = ProvingKey::build(); - let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); - assert!(proof.verify(&vk, &instances).is_ok()); - assert_eq!(proof.0.len(), expected_proof_size); - } - - #[test] - fn serialized_proof_test_case() { - use std::io::{Read, Write}; - - let vk = VerifyingKey::build(); - - fn write_test_case( - mut w: W, - instance: &Instance, - proof: &Proof, - ) -> std::io::Result<()> { - w.write_all(&instance.anchor.to_bytes())?; - w.write_all(&instance.cv_net.to_bytes())?; - w.write_all(&instance.nf_old.to_bytes())?; - w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; - w.write_all(&instance.cmx.to_bytes())?; - w.write_all(&[ - u8::from(instance.enable_spend), - u8::from(instance.enable_output), - ])?; - - w.write_all(proof.as_ref())?; - Ok(()) - } - - fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { - let read_32_bytes = |r: &mut R| { - let mut ret = [0u8; 32]; - r.read_exact(&mut ret).unwrap(); - ret - }; - let read_bool = |r: &mut R| { - let mut byte = [0u8; 1]; - r.read_exact(&mut byte).unwrap(); - match byte { - [0] => false, - [1] => true, - _ => panic!("Unexpected non-boolean byte"), - } - }; - - let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); - let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let rk = read_32_bytes(&mut r).try_into().unwrap(); - let cmx = - crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let enable_spend = read_bool(&mut r); - let enable_output = read_bool(&mut r); - let instance = - Instance::from_parts(anchor, cv_net, nf_old, rk, cmx, enable_spend, enable_output); - - let mut proof_bytes = vec![]; - r.read_to_end(&mut proof_bytes)?; - let proof = Proof::new(proof_bytes); - - Ok((instance, proof)) - } - - if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let mut rng = OsRng; - - let (circuit, instance) = generate_circuit_instance(OsRng); - let instances = &[instance.clone()]; - - let pk = ProvingKey::build(); - let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); - assert!(proof.verify(&vk, instances).is_ok()); - - let file = std::fs::File::create("circuit_proof_test_case.bin")?; - write_test_case(file, &instance, &proof) - }; - create_proof().expect("should be able to write new proof"); - } - - // Parse the hardcoded proof test case. - let (instance, proof) = { - let test_case_bytes = include_bytes!("circuit_proof_test_case.bin"); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - assert_eq!(proof.0.len(), 4992); - - assert!(proof.verify(&vk, &[instance]).is_ok()); - } - - #[cfg(feature = "dev-graph")] - #[test] - fn print_action_circuit() { - use plotters::prelude::*; - - let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root - .titled("Orchard Action Circuit", ("sans-serif", 60)) - .unwrap(); - - let circuit = Circuit { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - }; - halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) - .view_height(0..(1 << 11)) - .render(K, &circuit, &root) - .unwrap(); - } -} diff --git a/src/circuit_description b/src/circuit/circuit_description_vanilla similarity index 100% rename from src/circuit_description rename to src/circuit/circuit_description_vanilla diff --git a/src/circuit/circuit_description_zsa b/src/circuit/circuit_description_zsa new file mode 100644 index 000000000..535f080aa --- /dev/null +++ b/src/circuit/circuit_description_zsa @@ -0,0 +1,28969 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 33, + num_advice_columns: 10, + num_instance_columns: 1, + num_selectors: 60, + gates: [ + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2f70597a8e3d0f42f7a86a704f9bb232fe04a37f2b5a7c8c2aa7bd6e3af94367, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2d0e5169311919af1e917f63136d6c421d9ea766a7ffe3dba413c47eaf5af28e, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2f70597a8e3d0f42f7a86a704f9bb232fe04a37f2b5a7c8c2aa7bd6e3af94367, + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2d0e5169311919af1e917f63136d6c421d9ea766a7ffe3dba413c47eaf5af28e, + ), + ), + ), + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 18, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 0, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 10, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 3, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 0, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 10, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 3, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Product( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x2cc057f3fa14687acc59ffd00de864434543705f35e98ab5c6de463cd1404e6b, + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x32e7c439f2f967e55fd72b55df208385fadbf8ae7ae24796171840417cab7576, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x2eae5df8c3115969f461778abf6c91fa1403db6f50302040942645bd7d4464e0, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + ), + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x07bf368481067199db18b4aefe68d26d13f074fde9a18b29a1ca1516a4a1a6a0, + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x2aec6906c63f3cf1018a918b9dac5dadbb1d65040c85c1bfe82425bc1b23a059, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0952e0243aec2af01215944a64a246b276b2a7139db71b36e0541adf238e0781, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + ), + ), + Fixed { + query_index: 10, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x2fcbba6f9159a219723a63a0c09dab26aef9112e952fdbb52a418d8d73a7c908, + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x1ec7372574f3851bb4ddd4b4d6452256c5e4960d7424cd3776efab42d4fba90b, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0d0c2efd6472f12a3c26fa4b7d25b1e487a7435d30f8be81adc8933c6f3c72ee, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0020000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000100, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000400000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0200000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000100, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000400000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0200000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [ + ( + Column { + index: 0, + column_type: Instance, + }, + Rotation( + 0, + ), + ), + ], + fixed_queries: [ + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 19, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 20, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 21, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 22, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 23, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 24, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 25, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 26, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 27, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 28, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 29, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 30, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 31, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 32, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Instance, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 4, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Fixed, + }, + Column { + index: 10, + column_type: Fixed, + }, + Column { + index: 11, + column_type: Fixed, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 19, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 4, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), + (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), + (0x17e9ee15383a32a80bd1d4b3ae53c19389748922e9bf4dbc4884e20a472b10ef, 0x1947806a1f43a3f2b675ec6d46d1678d1f18374ef89ec2654152e454346b3add), + (0x365c3f7dfaa40ec708988a9392112df6725a65eb5f70b809025ee47e9dae145b, 0x1661613acd8709d05038f6d5ca5a8508c0dd881d5879d85dcd4ea48aa12875fc), + (0x178d86d072746921f193c4a1f24e0bc252c810e7fb4ca7dbb8258f7dfb45a547, 0x153d91d5ea619d522d5a4dfdbcef80686ed1328980f1dab8aea30357ce57bd0a), + (0x35d8b6e2ebbc57d08dea9e510d450b40b5a3dd4359f9f2a888610aff29ee3c23, 0x360e4b2ce85b08d0a9576207382c26de7ad35ce33f582b6eeedd72d406ff9cef), + (0x309fd7b620087579d276623592c791f36cd3424b2230a8e7d45dcaf586ed288b, 0x0e77ac0389e400aba724c636c13e01de338bbaa8c992a0174be3504204c15a26), + (0x3bd856be3b91aea580396400bc03d30de759946141fd92cda5d975b64b4f48c7, 0x1b8fb47363e53a6235dc03a8d1ee9e81ed13e8affb1ea7fc2228df24d6d795d5), + (0x15e059df5a9a5c7e33e31e5ab4f2629efc513bf6cffca27de6b279632b8f7b06, 0x2e715a322fad2b5bf21dbcb66c26dbffa26c4c00bb2a45ae30c456daa3a75a86), + (0x307aa50de381ca85af5aa98cb4b8f3c74d0e4b49d02929dda1e4f187de911e19, 0x032f3980542054f73b659cb328e7db6cef6ac537fc9cae3b09fb7b164cb542f5), + (0x0d0c4b42b87439e56df6f41f07d93367df6f5a64d273338b0d4c8c242b908849, 0x2ab0f7f461b85408e4d007d0fcb5fa6f70a18b42c373d515f7c1e55bc20c384c), + (0x251b9a858904eb93ea4b89b3a65ceacd637db066f16d1fa896eda84434d72950, 0x2c60a586cb79bcca811be1d1092a23131a6884ccb2d809f92e94c5a4d174b167), + (0x3b09db3011d8047afc6ea9c8f3787f9b1870affc14ab64a9433508050cd41d9f, 0x3903a28dcf729c1132353036fc2819a0d0dce6ceda266a388ae401026274e99a), + (0x244649d7c67dab9df822ad21a4a3e46afcc7e020c31c54563d78b81bc4ec4f18, 0x2d5ba72aca69c6a3d5a2c3fa22c5d0c4b91b340bd757b344caae739cece6efbe), + (0x18b67544d4466429760be2b231418b43d35d79462f8743051c8e437dd710035d, 0x2ca31a6106310316da5633fe4e16e2a0affafc4541b280a9722ae86219127aa0), + (0x1bc437a546b233020c7dfb4a62ec2720348e39160b45d0a6739df91eff962d75, 0x11f3c7e8df45cbd7d0e089000d0af3192b29e31edef31414897229edbf23b9e8), + (0x36579b3969fa8bb60eb3ea82410d5b440f5cadc10bba33c2f952d6e6e0647d2c, 0x332696aaf0ece706b633aeae97764c7b867e4be79c53f1a1ebed9053716d95df), + (0x2c47c46efa6b729a216455d1887eb910e21f50bedb97d48fd76f89e3abf4e5a4, 0x20da2ca8dde7430e2b663c22d10eeb6b511e341b6a29fe9dd094ab249da4f5db), + (0x12da47c8091b8de4fc979e49f7b173d352504f18ccc461ecc5bbe4a798078ba8, 0x2d7eb25b36bb9419d081f457f4424ffc9c3b47d558063bc5c58de550c041cdf9), + (0x33a7a93684fd8f5890cc6df73bfee688ff4c778b237afac6a00807d74750f07e, 0x09ba011a18d53d7cf20a020d179ba3a2dd93c1c5fa1c5906d51c16e78c15b2e1), + (0x2be5e08e9f02057bb5da2591660ea8ddd550114ad4e4751f0407e52424071469, 0x0761484d4ca67f3258780134d76837a261e262315f66c38d818efb7ee8fa9048), + (0x334105dd96996a08df56e88261dcd87c5356cfc0f2b8ae0a9419899d5def147b, 0x09ddf24ae765eda056cf59b16ac14464240c83e253135682c02e6546f89dd396), + (0x04706edf95516db26def46d92def64d6a61cb357ac5ace44a1015c33238778fa, 0x03560c6396e34aac8e541a7811eb0b7fb1b70262af59976f933135f3bf5b21b1), + (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), + (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), + (0x03b29c3e0e5df6f3ba9ce0fb052c0535c8a5b8288faba258ea9e8d6bd6fcf4b2, 0x2bb6c203fc3401bb6de372cd6c8cf7b973f0a6742f39f4b7ec80be443eb65e6c), + (0x1534590f918b8ec3c3f212bce6212e2706b9784926bc3f4c008932f3974b5244, 0x2767f413af8fea55f2226c21f9ae9c9bf9b14e3c181cf2cf94eb6e7efb024f71), + (0x3370cb937349996acaba056ebd00abe986a7d2b60151690da5f5ddebe9d2e644, 0x354521f558c5aad2e0d8b120c885a3a327e6fea64ab78a395317a2ecd542e17b), + (0x0513729700f3ff1cba8d080688f61eac7705283fcf9eb89bd30a539d2f810e32, 0x0ddf8fd425035d59dd4f7c3f7c51767bf9e2352b5a898aa06ee0bef28b468d1c), + (0x081c000b483d260442735f5220efb4f58220d165ef0eb9c89633d0c92d3d9f4b, 0x3be8b1162974276224d52329c972240dbebf5f4db5391c0af15d7253a4a76594), + (0x238572760915711b6ce8a15275a0cfb64d2080cda36053b44c6ead1b2fd8036f, 0x1689fcc8a2962850097bba60487c325070e63236aae3d60c89bf592dbc5405e6), + ], + permutation: VerifyingKey { + commitments: [ + (0x08c7dcef56c18bf78f712fe2c16781929e03b64117550c39e17bf2383084a262, 0x3e0484351466570def03cfba67249d1319bbc6ddd25bf83ebc7d86e502c099af), + (0x3bac5ab5303fbedef8955951cb40620418d47d813aedd62f5e8250b5d2e61d6e, 0x20da35a54cef9724662e2cb262954cfe6edd83bba4a5da78e963ef4a115f0ea8), + (0x1364f575d78b2fcc8227f020b97377aa6e5656b39538e62cb07ffcd523a0e8c4, 0x379bc25e8b3eaff7b52780614a6baf84bd9a114b51596cbf20d8ce5030059939), + (0x30dba0200970e98364c2d8d911700e12e648b1b530ec8f5959ebc9480bc9bdce, 0x1b50964ecea23e32fb3ee2c09e2898d14b293781750bbb3c237df8cfcd62fb93), + (0x346924d8eb634112cdadc6efddcdf33b8c7ca0d1d1ce6e08ca448403094ff556, 0x18f016b8560913fae264ad71a172935b88e044e1b8b147fa7dc7c63b56bf8351), + (0x1af9c9e534c43e4c3d1508bfd77b7d16cd764df511682f7ab2cd9dad9f918762, 0x36f70dcd60250de9208d26e0988e608e873df83d2484ff31ecf9fbfe23f391b3), + (0x01dda2447cbb6875d7600645c36341f692fe9255586eff537aa09b0c922436f3, 0x10d86b9d008679bbc1a8b657e2bd5fa7c5f59fd6c7ce8a911d3fe6820bded560), + (0x0198f863c3b0bb695922e22db57de978aa6a473524720a3411b195ba18206889, 0x223e3135e0dc4ee6e37b96c3a4bbf31522a250a2fbf3d46ba6305b24b8856d2d), + (0x227b5e52351a78a543ec665cba5c8d0f68a676c32b5ff5756bccb9185725b118, 0x3eb92023a61cccd8b150c223b22d73f0ab93a986b1898737f01cad79d1154aaa), + (0x06a4d7a90016ab77a50c8b62ee2406e28aaa19eae367e0898c28671691d9182f, 0x2580100de1db3945fa17446530ad9612cffb79ce2ef3a958f4fa3aa6caaa1695), + (0x024b6a9c117a288e3bae8949a94061ff99bc1d9419d663fed2382925ac6d74f4, 0x0d4da543cd644e5340091759177e3eb31a080909f24b0e606dafc701608fe6aa), + (0x04201f7a9c50a80bf2bd23957dbc2d45982fb413015aeedf32333957b0a65774, 0x31f8f5844762616c90a802a85bf658effdf70a2523a94e812ae9063640488075), + (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), + (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), + (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), + ], + }, +} diff --git a/src/circuit_proof_test_case.bin b/src/circuit/circuit_proof_test_case_vanilla.bin similarity index 100% rename from src/circuit_proof_test_case.bin rename to src/circuit/circuit_proof_test_case_vanilla.bin diff --git a/src/circuit/circuit_proof_test_case_zsa.bin b/src/circuit/circuit_proof_test_case_zsa.bin new file mode 100644 index 000000000..22cbd6477 Binary files /dev/null and b/src/circuit/circuit_proof_test_case_zsa.bin differ diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs new file mode 100644 index 000000000..4fcb95ce2 --- /dev/null +++ b/src/circuit/circuit_vanilla.rs @@ -0,0 +1,873 @@ +//! The Orchard Action circuit implementation for the Vanilla variation of the Orchard protocol. +//! +//! Includes the configuration, synthesis, and proof verification logic. + +use group::Curve; + +use pasta_curves::pallas; + +use halo2_gadgets::{ + ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, + poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip}, + sinsemilla::{ + chip::SinsemillaChip, + merkle::{chip::MerkleChip, MerklePath}, + }, + utilities::lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfig, PallasLookupRangeCheckConfig, + }, +}; +use halo2_proofs::{ + circuit::{Layouter, Value}, + plonk::{self, Constraints, Expression}, + poly::Rotation, +}; + +use crate::{ + circuit::commit_ivk::gadgets::commit_ivk, + circuit::derive_nullifier::gadgets::derive_nullifier, + circuit::note_commit::gadgets::note_commit, + circuit::value_commit_orchard::gadgets::value_commit_orchard, + circuit::{Config, Witnesses}, + constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, + orchard_flavor::OrchardVanilla, +}; + +use super::{ + commit_ivk::CommitIvkChip, + gadget::{add_chip::AddChip, assign_free_advice}, + note_commit::NoteCommitChip, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X, + RK_Y, +}; + +impl OrchardCircuit for OrchardVanilla { + type Config = Config; + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + // Advice columns used in the Orchard circuit. + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Constrain v_old - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + // Either v_old = 0, or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). + // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). + let q_orchard = meta.selector(); + meta.create_gate("Orchard circuit checks", |meta| { + let q_orchard = meta.query_selector(q_orchard); + let v_old = meta.query_advice(advices[0], Rotation::cur()); + let v_new = meta.query_advice(advices[1], Rotation::cur()); + let magnitude = meta.query_advice(advices[2], Rotation::cur()); + let sign = meta.query_advice(advices[3], Rotation::cur()); + + let root = meta.query_advice(advices[4], Rotation::cur()); + let anchor = meta.query_advice(advices[5], Rotation::cur()); + + let enable_spends = meta.query_advice(advices[6], Rotation::cur()); + let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); + + let one = Expression::Constant(pallas::Base::one()); + + Constraints::with_selector( + q_orchard, + [ + ( + "v_old - v_new = magnitude * sign", + v_old.clone() - v_new.clone() - magnitude * sign, + ), + ( + "Either v_old = 0, or root = anchor", + v_old.clone() * (root - anchor), + ), + ( + "v_old = 0 or enable_spends = 1", + v_old * (one.clone() - enable_spends), + ), + ( + "v_new = 0 or enable_outputs = 1", + v_new * (one - enable_outputs), + ), + ], + ) + }); + + // Addition of two field elements. + let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); + + // Fixed columns for the Sinsemilla generator lookup table + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + // Permutation over all advice columns. + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Poseidon requires four advice columns, while ECC incomplete addition requires + // six, so we could choose to configure them in parallel. However, we only use a + // single Poseidon invocation, and we have the rows to accommodate it serially. + // Instead, we reduce the proof size by sharing fixed columns between the ECC and + // Poseidon chips. + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); + let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); + + // Also use the first Lagrange coefficient column for loading global constants. + // It's free real estate :) + meta.enable_constant(lagrange_coeffs[0]); + + // We have a lot of free space in the right-most advice columns; use one of them + // for all of our range checks. + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + + // Configuration for curve point operations. + // This uses 10 advice columns and spans the whole circuit. + let ecc_config = + EccChip::::configure(meta, advices, lagrange_coeffs, range_check); + + // Configuration for the Poseidon hash. + let poseidon_config = PoseidonChip::configure::( + meta, + // We place the state columns after the partial_sbox column so that the + // pad-and-add region can be laid out more efficiently. + advices[6..9].try_into().unwrap(), + advices[5], + rc_a, + rc_b, + ); + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_1, merkle_config_1) = { + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + false, + ); + let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); + + (sinsemilla_config_1, merkle_config_1) + }; + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_2, merkle_config_2) = { + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + false, + ); + let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); + + (sinsemilla_config_2, merkle_config_2) + }; + + // Configuration to handle decomposition and canonicity checking + // for CommitIvk. + let commit_ivk_config = CommitIvkChip::configure(meta, advices); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_old. + let old_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone(), false); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_new. + let new_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone(), false); + + Config { + primary, + q_orchard, + advices, + add_config, + ecc_config, + poseidon_config, + merkle_config_1, + merkle_config_2, + sinsemilla_config_1, + sinsemilla_config_2, + commit_ivk_config, + old_note_commit_config, + new_note_commit_config, + } + } + + #[allow(non_snake_case)] + fn synthesize( + circuit: &Witnesses, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; + + // Construct the ECC chip. + let ecc_chip = config.ecc_chip(); + + // Witness private inputs that are used across multiple checks. + let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = { + // Witness psi_old + let psi_old = assign_free_advice( + layouter.namespace(|| "witness psi_old"), + config.advices[0], + circuit.psi_old, + )?; + + // Witness rho_old + let rho_old = assign_free_advice( + layouter.namespace(|| "witness rho_old"), + config.advices[0], + circuit.rho_old.map(|rho| rho.into_inner()), + )?; + + // Witness cm_old + let cm_old = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "cm_old"), + circuit.cm_old.as_ref().map(|cm| cm.inner().to_affine()), + )?; + + // Witness g_d_old + let g_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "gd_old"), + circuit.g_d_old.as_ref().map(|gd| gd.to_affine()), + )?; + + // Witness ak_P. + let ak_P: Value = circuit.ak.as_ref().map(|ak| ak.into()); + let ak_P = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness ak_P"), + ak_P.map(|ak_P| ak_P.to_affine()), + )?; + + // Witness nk. + let nk = assign_free_advice( + layouter.namespace(|| "witness nk"), + config.advices[0], + circuit.nk.map(|nk| nk.inner()), + )?; + + // Witness v_old. + let v_old = assign_free_advice( + layouter.namespace(|| "witness v_old"), + config.advices[0], + circuit.v_old, + )?; + + // Witness v_new. + let v_new = assign_free_advice( + layouter.namespace(|| "witness v_new"), + config.advices[0], + circuit.v_new, + )?; + + (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) + }; + + // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + let root = { + let path = circuit + .path + .map(|typed_path| typed_path.map(|node| node.inner())); + let merkle_inputs = MerklePath::construct( + [config.merkle_chip_1(), config.merkle_chip_2()], + OrchardHashDomains::MerkleCrh, + circuit.pos, + path, + ); + let leaf = cm_old.extract_p().inner().clone(); + merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? + }; + + // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + let v_net_magnitude_sign = { + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + let v_net = circuit.v_old - circuit.v_new; + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + circuit.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + let cv_net = value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), + ecc_chip.clone(), + v_net_magnitude_sign.clone(), + rcv, + None, + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; + + // Return the magnitude and sign so we can use them in the Orchard gate. + v_net_magnitude_sign + }; + + // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). + let nf_old = { + let nf_old = derive_nullifier( + &mut layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), + config.poseidon_chip(), + config.add_chip(), + ecc_chip.clone(), + rho_old.clone(), + &psi_old, + &cm_old, + nk.clone(), + None, + )?; + + // Constrain nf_old to equal public input + layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; + + nf_old + }; + + // Spend authority (https://p.z.cash/ZKS:action-spend-authority) + { + let alpha = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "alpha"), + circuit.alpha, + )?; + + // alpha_commitment = [alpha] SpendAuthG + let (alpha_commitment, _) = { + let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; + let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); + spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? + }; + + // [alpha] SpendAuthG + ak_P + let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; + + // Constrain rk to equal public input + layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; + layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; + } + + // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). + let pk_d_old = { + let ivk = { + let ak = ak_P.extract_p().inner().clone(); + let rivk = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + circuit.rivk.map(|rivk| rivk.inner()), + )?; + + commit_ivk( + config.sinsemilla_chip_1(), + ecc_chip.clone(), + config.commit_ivk_chip(), + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk, + )? + }; + let ivk = + ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; + + // [ivk] g_d_old + // The scalar value is passed through and discarded. + let (derived_pk_d_old, _ivk) = + g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; + + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). + let pk_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_old"), + circuit + .pk_d_old + .map(|pk_d_old| pk_d_old.inner().to_affine()), + )?; + derived_pk_d_old + .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; + + pk_d_old + }; + + // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). + { + let rcm_old = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm_old"), + circuit.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let derived_cm_old = note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_1(), + config.ecc_chip(), + config.note_commit_chip_old(), + g_d_old.inner(), + pk_d_old.inner(), + v_old.clone(), + rho_old, + psi_old, + rcm_old, + None, + )?; + + // Constrain derived cm_old to equal witnessed cm_old + derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; + } + + // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). + { + // Witness g_d_new + let g_d_new = { + let g_d_new = circuit.g_d_new.map(|g_d_new| g_d_new.to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d_new_star"), + g_d_new, + )? + }; + + // Witness pk_d_new + let pk_d_new = { + let pk_d_new = circuit + .pk_d_new + .map(|pk_d_new| pk_d_new.inner().to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_new"), + pk_d_new, + )? + }; + + // ρ^new = nf^old + let rho_new = nf_old.inner().clone(); + + // Witness psi_new + let psi_new = assign_free_advice( + layouter.namespace(|| "witness psi_new"), + config.advices[0], + circuit.psi_new, + )?; + + let rcm_new = ScalarFixed::new( + ecc_chip, + layouter.namespace(|| "rcm_new"), + circuit.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let cm_new = note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_2(), + config.ecc_chip(), + config.note_commit_chip_new(), + g_d_new.inner(), + pk_d_new.inner(), + v_new.clone(), + rho_new, + psi_new, + rcm_new, + None, + )?; + + let cmx = cm_new.extract_p(); + + // Constrain cmx to equal public input + layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; + } + + // Constrain the remaining Orchard circuit checks. + layouter.assign_region( + || "Orchard circuit checks", + |mut region| { + v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; + v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; + v_net_magnitude_sign.0.copy_advice( + || "v_net magnitude", + &mut region, + config.advices[2], + 0, + )?; + v_net_magnitude_sign.1.copy_advice( + || "v_net sign", + &mut region, + config.advices[3], + 0, + )?; + + root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; + region.assign_advice_from_instance( + || "pub input anchor", + config.primary, + ANCHOR, + config.advices[5], + 0, + )?; + + region.assign_advice_from_instance( + || "enable spends", + config.primary, + ENABLE_SPEND, + config.advices[6], + 0, + )?; + + region.assign_advice_from_instance( + || "enable outputs", + config.primary, + ENABLE_OUTPUT, + config.advices[7], + 0, + )?; + + config.q_orchard.enable(&mut region, 0) + }, + )?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use core::iter; + + use ff::Field; + use halo2_proofs::{circuit::Value, dev::MockProver}; + use pasta_curves::pallas; + use rand::{rngs::OsRng, RngCore}; + + use crate::circuit::Witnesses; + use crate::{ + bundle::Flags, + circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, + keys::SpendValidatingKey, + note::{AssetBase, Note, Rho}, + orchard_flavor::OrchardVanilla, + tree::MerklePath, + value::{ValueCommitTrapdoor, ValueCommitment}, + }; + + type OrchardCircuitVanilla = Circuit; + + fn generate_circuit_instance(mut rng: R) -> (OrchardCircuitVanilla, Instance) { + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let sender_address = spent_note.recipient(); + let nk = *fvk.nk(); + let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); + let nf_old = spent_note.nullifier(&fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = fvk.into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let (_, _, output_note) = Note::dummy(&mut rng, Some(rho), AssetBase::native()); + let cmx = output_note.commitment().into(); + + let value = spent_note.value() - output_note.value(); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let psi_old = spent_note.rseed().psi(&spent_note.rho()); + + ( + OrchardCircuitVanilla { + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, + phantom: std::marker::PhantomData, + }, + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: false, + }, + ) + } + + // TODO: recast as a proptest + #[test] + fn round_trip() { + let mut rng = OsRng; + + let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) + .map(|()| generate_circuit_instance(&mut rng)) + .unzip(); + + let vk = VerifyingKey::build::(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + // panic!("{:#?}", vk.vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.vk.pinned()), + include_str!("circuit_description_vanilla").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + let expected_proof_size = { + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure( + K, + &circuits[0], + ); + println!("{:#?}", circuit_cost); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 4992); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7264); + usize::from(circuit_cost.proof_size(instances.len())) + }; + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + assert_eq!( + MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect() + ) + .unwrap() + .verify(), + Ok(()) + ); + } + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, &instances).is_ok()); + assert_eq!(proof.0.len(), expected_proof_size); + } + + #[test] + fn serialized_proof_test_case() { + use std::io::{Read, Write}; + + let vk = VerifyingKey::build::(); + + fn write_test_case( + mut w: W, + instance: &Instance, + proof: &Proof, + ) -> std::io::Result<()> { + w.write_all(&instance.anchor.to_bytes())?; + w.write_all(&instance.cv_net.to_bytes())?; + w.write_all(&instance.nf_old.to_bytes())?; + w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; + w.write_all(&instance.cmx.to_bytes())?; + w.write_all(&[ + u8::from(instance.enable_spend), + u8::from(instance.enable_output), + ])?; + + w.write_all(proof.as_ref())?; + Ok(()) + } + + fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { + let read_32_bytes = |r: &mut R| { + let mut ret = [0u8; 32]; + r.read_exact(&mut ret).unwrap(); + ret + }; + let read_bool = |r: &mut R| { + let mut byte = [0u8; 1]; + r.read_exact(&mut byte).unwrap(); + match byte { + [0] => false, + [1] => true, + _ => panic!("Unexpected non-boolean byte"), + } + }; + + let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); + let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let rk = read_32_bytes(&mut r).try_into().unwrap(); + let cmx = + crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let enable_spend = read_bool(&mut r); + let enable_output = read_bool(&mut r); + let enable_zsa = false; + let instance = Instance::from_parts( + anchor, + cv_net, + nf_old, + rk, + cmx, + Flags::from_parts(enable_spend, enable_output, enable_zsa), + ); + + let mut proof_bytes = vec![]; + r.read_to_end(&mut proof_bytes)?; + let proof = Proof::new(proof_bytes); + + Ok((instance, proof)) + } + + if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let mut rng = OsRng; + + let (circuit, instance) = generate_circuit_instance(OsRng); + let instances = &[instance.clone()]; + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, instances).is_ok()); + + let file = std::fs::File::create("circuit_proof_test_case.bin")?; + write_test_case(file, &instance, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let (instance, proof) = { + let test_case_bytes = include_bytes!("circuit_proof_test_case_vanilla.bin"); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + assert_eq!(proof.0.len(), 4992); + + assert!(proof.verify(&vk, &[instance]).is_ok()); + } + + #[cfg(feature = "dev-graph")] + #[test] + fn print_action_circuit() { + use plotters::prelude::*; + + let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root + .titled("Orchard Action Circuit", ("sans-serif", 60)) + .unwrap(); + + let circuit = OrchardCircuitVanilla { + witnesses: Witnesses::default(), + phantom: std::marker::PhantomData, + }; + halo2_proofs::dev::CircuitLayout::default() + .show_labels(false) + .view_height(0..(1 << 11)) + .render(K, &circuit, &root) + .unwrap(); + } +} diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs new file mode 100644 index 000000000..d87180a60 --- /dev/null +++ b/src/circuit/circuit_zsa.rs @@ -0,0 +1,1411 @@ +//! The Orchard Action circuit implementation for the ZSA variation of the Orchard protocol. +//! +//! Includes the configuration, synthesis, and proof verification logic. + +use ff::Field; + +use group::Curve; + +use pasta_curves::{arithmetic::CurveAffine, pallas}; + +use halo2_gadgets::{ + ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, + poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip}, + sinsemilla::{ + chip::SinsemillaChip, + merkle::{chip::MerkleChip, MerklePath}, + }, + utilities::{ + bool_check, + lookup_range_check::{LookupRangeCheck4_5BConfig, PallasLookupRangeCheck4_5BConfig}, + }, +}; + +use halo2_proofs::{ + circuit::{Layouter, Value}, + plonk::{self, Constraints, Expression}, + poly::Rotation, +}; + +use super::{ + commit_ivk::CommitIvkChip, + derive_nullifier::ZsaNullifierParams, + gadget::{add_chip::AddChip, assign_free_advice, assign_is_native_asset, assign_split_flag}, + note_commit::NoteCommitChip, + value_commit_orchard::ZsaValueCommitParams, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, ENABLE_ZSA, + NF_OLD, RK_X, RK_Y, +}; +use crate::{ + circuit::commit_ivk::gadgets::commit_ivk, + circuit::derive_nullifier::gadgets::derive_nullifier, + circuit::note_commit::{gadgets::note_commit, ZsaNoteCommitParams}, + circuit::value_commit_orchard::gadgets::value_commit_orchard, + circuit::{Config, Witnesses}, + constants::OrchardFixedBasesFull, + constants::{OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, + orchard_flavor::OrchardZSA, +}; + +impl OrchardCircuit for OrchardZSA { + type Config = Config; + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + // Advice columns used in the Orchard circuit. + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // The new or updated constraints for OrchardZSA are explained in + // [ZIP-226: Transfer and Burn of Zcash Shielded Assets][circuitstatement]. + // + // All OrchardZSA constraints: + // Constrain split_flag to be boolean + // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign + // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) + // Constrain v_old = 0 or enable_spends = 1 + // Constrain v_new = 0 or enable_outputs = 1 + // Constrain is_native_asset to be boolean + // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset + // Constraint if split_flag = 0 then psi_old = psi_nf + // Constraint if split_flag = 1, then is_native_asset = 0 + // Constraint if enable_zsa = 0, then is_native_asset = 1 + // + // [circuitstatement]: https://zips.z.cash/zip-0226#circuit-statement + let q_orchard = meta.selector(); + meta.create_gate("Orchard circuit checks", |meta| { + let q_orchard = meta.query_selector(q_orchard); + let v_old = meta.query_advice(advices[0], Rotation::cur()); + let v_new = meta.query_advice(advices[1], Rotation::cur()); + let magnitude = meta.query_advice(advices[2], Rotation::cur()); + let sign = meta.query_advice(advices[3], Rotation::cur()); + + let root = meta.query_advice(advices[4], Rotation::cur()); + let anchor = meta.query_advice(advices[5], Rotation::cur()); + + let enable_spends = meta.query_advice(advices[6], Rotation::cur()); + let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); + + let split_flag = meta.query_advice(advices[8], Rotation::cur()); + + let is_native_asset = meta.query_advice(advices[9], Rotation::cur()); + let asset_x = meta.query_advice(advices[0], Rotation::next()); + let asset_y = meta.query_advice(advices[1], Rotation::next()); + let diff_asset_x_inv = meta.query_advice(advices[2], Rotation::next()); + let diff_asset_y_inv = meta.query_advice(advices[3], Rotation::next()); + + let one = Expression::Constant(pallas::Base::one()); + + let native_asset = AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap(); + + let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); + let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); + + let psi_old = meta.query_advice(advices[4], Rotation::next()); + let psi_nf = meta.query_advice(advices[5], Rotation::next()); + + let enable_zsa = meta.query_advice(advices[6], Rotation::next()); + + Constraints::with_selector( + q_orchard, + [ + ("bool_check split_flag", bool_check(split_flag.clone())), + ( + "v_old * (1 - split_flag) - v_new = magnitude * sign", + v_old.clone() * (one.clone() - split_flag.clone()) + - v_new.clone() + - magnitude * sign, + ), + // We already checked that + // * is_native_asset is boolean (just below), and + // * v_old is a 64 bit unsigned integer (in the note commitment evaluation). + // So, 1 - is_native_asset + v_old = 0 only when (is_native_asset = 1 and v_old = 0), no overflow can occur. + ( + "(v_old = 0 and is_native_asset = 1) or (root = anchor)", + (v_old.clone() + one.clone() - is_native_asset.clone()) * (root - anchor), + ), + ( + "v_old = 0 or enable_spends = 1", + v_old * (one.clone() - enable_spends), + ), + ( + "v_new = 0 or enable_outputs = 1", + v_new * (one.clone() - enable_outputs), + ), + ( + "bool_check is_native_asset", + bool_check(is_native_asset.clone()), + ), + ( + "(is_native_asset = 1) => (asset_x = native_asset_x)", + is_native_asset.clone() * diff_asset_x.clone(), + ), + ( + "(is_native_asset = 1) => (asset_y = native_asset_y)", + is_native_asset.clone() * diff_asset_y.clone(), + ), + // To prove that `asset` is not equal to `native_asset`, we will prove that at + // least one of `x(asset) - x(native_asset)` or `y(asset) - y(native_asset)` is + // not equal to zero. + // To prove that `x(asset) - x(native_asset)` (resp `y(asset) - y(native_asset)`) + // is not equal to zero, we will prove that it is invertible. + ( + "(is_native_asset = 0) => (asset != native_asset)", + (one.clone() - is_native_asset.clone()) + * (diff_asset_x * diff_asset_x_inv - one.clone()) + * (diff_asset_y * diff_asset_y_inv - one.clone()), + ), + ( + "(split_flag = 0) => (psi_old = psi_nf)", + (one.clone() - split_flag.clone()) * (psi_old - psi_nf), + ), + ( + "(split_flag = 1) => (is_native_asset = 0)", + split_flag * is_native_asset.clone(), + ), + ( + "(enable_zsa = 0) => (is_native_asset = 1)", + (one.clone() - enable_zsa) * (one - is_native_asset), + ), + ], + ) + }); + + // Addition of two field elements. + let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); + + // Fixed columns for the Sinsemilla generator lookup table + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + // Permutation over all advice columns. + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Poseidon requires four advice columns, while ECC incomplete addition requires + // six, so we could choose to configure them in parallel. However, we only use a + // single Poseidon invocation, and we have the rows to accommodate it serially. + // Instead, we reduce the proof size by sharing fixed columns between the ECC and + // Poseidon chips. + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); + let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); + + // Also use the first Lagrange coefficient column for loading global constants. + // It's free real estate :) + meta.enable_constant(lagrange_coeffs[0]); + + // We have a lot of free space in the right-most advice columns; use one of them + // for all of our range checks. + let range_check = LookupRangeCheck4_5BConfig::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); + + // Configuration for curve point operations. + // This uses 10 advice columns and spans the whole circuit. + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + // Configuration for the Poseidon hash. + let poseidon_config = PoseidonChip::configure::( + meta, + // We place the state columns after the partial_sbox column so that the + // pad-and-add region can be laid out more efficiently. + advices[6..9].try_into().unwrap(), + advices[5], + rc_a, + rc_b, + ); + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_1, merkle_config_1) = { + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + true, + ); + let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); + + (sinsemilla_config_1, merkle_config_1) + }; + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_2, merkle_config_2) = { + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + true, + ); + let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); + + (sinsemilla_config_2, merkle_config_2) + }; + + // Configuration to handle decomposition and canonicity checking + // for CommitIvk. + let commit_ivk_config = CommitIvkChip::configure(meta, advices); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_old. + let old_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone(), true); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_new. + let new_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone(), true); + + Config { + primary, + q_orchard, + advices, + add_config, + ecc_config, + poseidon_config, + merkle_config_1, + merkle_config_2, + sinsemilla_config_1, + sinsemilla_config_2, + commit_ivk_config, + old_note_commit_config, + new_note_commit_config, + } + } + + #[allow(non_snake_case)] + fn synthesize( + circuit: &Witnesses, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; + + // Construct the ECC chip. + let ecc_chip = config.ecc_chip(); + + // Witness private inputs that are used across multiple checks. + let (psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { + // Witness psi_nf + let psi_nf = assign_free_advice( + layouter.namespace(|| "witness psi_nf"), + config.advices[0], + circuit.psi_nf, + )?; + + // Witness psi_old + let psi_old = assign_free_advice( + layouter.namespace(|| "witness psi_old"), + config.advices[0], + circuit.psi_old, + )?; + + // Witness rho_old + let rho_old = assign_free_advice( + layouter.namespace(|| "witness rho_old"), + config.advices[0], + circuit.rho_old.map(|rho| rho.into_inner()), + )?; + + // Witness cm_old + let cm_old = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "cm_old"), + circuit.cm_old.as_ref().map(|cm| cm.inner().to_affine()), + )?; + + // Witness g_d_old + let g_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "gd_old"), + circuit.g_d_old.as_ref().map(|gd| gd.to_affine()), + )?; + + // Witness ak_P. + let ak_P: Value = circuit.ak.as_ref().map(|ak| ak.into()); + let ak_P = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness ak_P"), + ak_P.map(|ak_P| ak_P.to_affine()), + )?; + + // Witness nk. + let nk = assign_free_advice( + layouter.namespace(|| "witness nk"), + config.advices[0], + circuit.nk.map(|nk| nk.inner()), + )?; + + // Witness v_old. + let v_old = assign_free_advice( + layouter.namespace(|| "witness v_old"), + config.advices[0], + circuit.v_old, + )?; + + // Witness v_new. + let v_new = assign_free_advice( + layouter.namespace(|| "witness v_new"), + config.advices[0], + circuit.v_new, + )?; + + // Witness asset + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + circuit.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + ( + psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, + ) + }; + + // Witness split_flag + let split_flag = assign_split_flag( + layouter.namespace(|| "witness split_flag"), + config.advices[0], + circuit.split_flag, + )?; + + // Witness is_native_asset which is equal to + // 1 if asset is equal to native asset, and + // 0 if asset is not equal to native asset. + let is_native_asset = assign_is_native_asset( + layouter.namespace(|| "witness is_native_asset"), + config.advices[0], + circuit.asset, + )?; + + // Merkle path validity check. + let root = { + let path = circuit + .path + .map(|typed_path| typed_path.map(|node| node.inner())); + let merkle_inputs = MerklePath::construct( + [config.merkle_chip_1(), config.merkle_chip_2()], + OrchardHashDomains::MerkleCrh, + circuit.pos, + path, + ); + let leaf = cm_old.extract_p().inner().clone(); + merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? + }; + + // Value commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][valuecommitcorrectness] for more details. + // + // [valuecommitcorrectness]: https://zips.z.cash/zip-0226#value-commitment-correctness + let v_net_magnitude_sign = { + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + // v_net is equal to + // (-v_new) if split_flag = true + // v_old - v_new if split_flag = false + let v_net = circuit.split_flag.and_then(|split_flag| { + if split_flag { + Value::known(crate::value::NoteValue::zero()) - circuit.v_new + } else { + circuit.v_old - circuit.v_new + } + }); + + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + circuit.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + let cv_net = value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), + ecc_chip.clone(), + v_net_magnitude_sign.clone(), + rcv, + Some(ZsaValueCommitParams { + sinsemilla_chip: config.sinsemilla_chip_1(), + asset: asset.clone(), + }), + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; + + // Return the magnitude and sign so we can use them in the Orchard gate. + v_net_magnitude_sign + }; + + // Nullifier integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] for more details. + // + // [zip226]: https://zips.z.cash/zip-0226 + let nf_old = { + let nf_old = derive_nullifier( + &mut layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), + config.poseidon_chip(), + config.add_chip(), + ecc_chip.clone(), + rho_old.clone(), + &psi_nf, + &cm_old, + nk.clone(), + Some(ZsaNullifierParams { + cond_swap_chip: config.cond_swap_chip(), + split_flag: split_flag.clone(), + }), + )?; + + // Constrain nf_old to equal public input + layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; + + nf_old + }; + + // Spend authority + { + let alpha = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "alpha"), + circuit.alpha, + )?; + + // alpha_commitment = [alpha] SpendAuthG + let (alpha_commitment, _) = { + let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; + let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); + spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? + }; + + // [alpha] SpendAuthG + ak_P + let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; + + // Constrain rk to equal public input + layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; + layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; + } + + // Diversified address integrity. + let pk_d_old = { + let ivk = { + let ak = ak_P.extract_p().inner().clone(); + let rivk = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + circuit.rivk.map(|rivk| rivk.inner()), + )?; + + commit_ivk( + config.sinsemilla_chip_1(), + ecc_chip.clone(), + config.commit_ivk_chip(), + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk, + )? + }; + let ivk = + ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; + + // [ivk] g_d_old + // The scalar value is passed through and discarded. + let (derived_pk_d_old, _ivk) = + g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; + + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). + let pk_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_old"), + circuit + .pk_d_old + .map(|pk_d_old| pk_d_old.inner().to_affine()), + )?; + derived_pk_d_old + .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; + + pk_d_old + }; + + // Old note commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit] for more details. + // + // [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment. + { + let rcm_old = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm_old"), + circuit.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let derived_cm_old = note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_1(), + config.ecc_chip(), + config.note_commit_chip_old(), + g_d_old.inner(), + pk_d_old.inner(), + v_old.clone(), + rho_old, + psi_old.clone(), + rcm_old, + Some(ZsaNoteCommitParams { + cond_swap_chip: config.cond_swap_chip(), + asset: asset.inner().clone(), + is_native_asset: is_native_asset.clone(), + }), + )?; + + // Constrain derived cm_old to equal witnessed cm_old + derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; + } + + // New note commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit] for more details. + // + // [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment. + { + // Witness g_d_new + let g_d_new = { + let g_d_new = circuit.g_d_new.map(|g_d_new| g_d_new.to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d_new_star"), + g_d_new, + )? + }; + + // Witness pk_d_new + let pk_d_new = { + let pk_d_new = circuit + .pk_d_new + .map(|pk_d_new| pk_d_new.inner().to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_new"), + pk_d_new, + )? + }; + + // ρ^new = nf^old + let rho_new = nf_old.inner().clone(); + + // Witness psi_new + let psi_new = assign_free_advice( + layouter.namespace(|| "witness psi_new"), + config.advices[0], + circuit.psi_new, + )?; + + let rcm_new = ScalarFixed::new( + ecc_chip, + layouter.namespace(|| "rcm_new"), + circuit.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let cm_new = note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_2(), + config.ecc_chip(), + config.note_commit_chip_new(), + g_d_new.inner(), + pk_d_new.inner(), + v_new.clone(), + rho_new, + psi_new, + rcm_new, + Some(ZsaNoteCommitParams { + cond_swap_chip: config.cond_swap_chip(), + asset: asset.inner().clone(), + is_native_asset: is_native_asset.clone(), + }), + )?; + + let cmx = cm_new.extract_p(); + + // Constrain cmx to equal public input + layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; + } + + // Constrain the remaining Orchard circuit checks. + layouter.assign_region( + || "Orchard circuit checks", + |mut region| { + v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; + v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; + v_net_magnitude_sign.0.copy_advice( + || "v_net magnitude", + &mut region, + config.advices[2], + 0, + )?; + v_net_magnitude_sign.1.copy_advice( + || "v_net sign", + &mut region, + config.advices[3], + 0, + )?; + + root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; + region.assign_advice_from_instance( + || "pub input anchor", + config.primary, + ANCHOR, + config.advices[5], + 0, + )?; + + region.assign_advice_from_instance( + || "enable spends", + config.primary, + ENABLE_SPEND, + config.advices[6], + 0, + )?; + + region.assign_advice_from_instance( + || "enable outputs", + config.primary, + ENABLE_OUTPUT, + config.advices[7], + 0, + )?; + + split_flag.copy_advice(|| "split_flag", &mut region, config.advices[8], 0)?; + + is_native_asset.copy_advice( + || "is_native_asset", + &mut region, + config.advices[9], + 0, + )?; + asset + .inner() + .x() + .copy_advice(|| "asset_x", &mut region, config.advices[0], 1)?; + asset + .inner() + .y() + .copy_advice(|| "asset_y", &mut region, config.advices[1], 1)?; + + // `diff_asset_x_inv` and `diff_asset_y_inv` will be used to prove that + // if is_native_asset = 0, then asset != native_asset. + region.assign_advice( + || "diff_asset_x_inv", + config.advices[2], + 1, + || { + circuit.asset.map(|asset| { + let asset_x = *asset.cv_base().to_affine().coordinates().unwrap().x(); + let native_asset_x = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .x(); + + let diff_asset_x = asset_x - native_asset_x; + + if diff_asset_x == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_x.invert().unwrap() + } + }) + }, + )?; + region.assign_advice( + || "diff_asset_y_inv", + config.advices[3], + 1, + || { + circuit.asset.map(|asset| { + let asset_y = *asset.cv_base().to_affine().coordinates().unwrap().y(); + let native_asset_y = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .y(); + + let diff_asset_y = asset_y - native_asset_y; + + if diff_asset_y == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_y.invert().unwrap() + } + }) + }, + )?; + + psi_old.copy_advice(|| "psi_old", &mut region, config.advices[4], 1)?; + psi_nf.copy_advice(|| "psi_nf", &mut region, config.advices[5], 1)?; + + region.assign_advice_from_instance( + || "enable zsa", + config.primary, + ENABLE_ZSA, + config.advices[6], + 1, + )?; + + config.q_orchard.enable(&mut region, 0) + }, + )?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use core::iter; + + use ff::Field; + use group::{Curve, Group, GroupEncoding}; + use halo2_proofs::{circuit::Value, dev::MockProver}; + use pasta_curves::pallas; + use rand::{rngs::OsRng, RngCore}; + + use crate::circuit::Witnesses; + use crate::{ + builder::SpendInfo, + bundle::Flags, + circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, + keys::{FullViewingKey, Scope, SpendValidatingKey, SpendingKey}, + note::{commitment::NoteCommitTrapdoor, AssetBase, Note, NoteCommitment, Nullifier, Rho}, + orchard_flavor::OrchardZSA, + primitives::redpallas::VerificationKey, + tree::MerklePath, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, + }; + + type OrchardCircuitZSA = Circuit; + + fn generate_dummy_circuit_instance(mut rng: R) -> (OrchardCircuitZSA, Instance) { + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let sender_address = spent_note.recipient(); + let nk = *fvk.nk(); + let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); + let nf_old = spent_note.nullifier(&fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = fvk.into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let (_, _, output_note) = Note::dummy(&mut rng, Some(rho), AssetBase::native()); + let cmx = output_note.commitment().into(); + + let value = spent_note.value() - output_note.value(); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let psi_old = spent_note.rseed().psi(&spent_note.rho()); + + ( + OrchardCircuitZSA { + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(psi_old), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, + phantom: std::marker::PhantomData, + }, + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: false, + }, + ) + } + + // TODO: recast as a proptest + #[test] + fn round_trip() { + let mut rng = OsRng; + + let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) + .map(|()| generate_dummy_circuit_instance(&mut rng)) + .unzip(); + + let vk = VerifyingKey::build::(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + // panic!("{:#?}", vk.vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.vk.pinned()), + include_str!("circuit_description_zsa").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + let expected_proof_size = { + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure( + K, + &circuits[0], + ); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 5120); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7392); + usize::from(circuit_cost.proof_size(instances.len())) + }; + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + assert_eq!( + MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect() + ) + .unwrap() + .verify(), + Ok(()) + ); + } + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, &instances).is_ok()); + assert_eq!(proof.0.len(), expected_proof_size); + } + + #[test] + fn serialized_proof_test_case() { + use std::fs; + use std::io::{Read, Write}; + + let vk = VerifyingKey::build::(); + + fn write_test_case( + mut w: W, + instance: &Instance, + proof: &Proof, + ) -> std::io::Result<()> { + w.write_all(&instance.anchor.to_bytes())?; + w.write_all(&instance.cv_net.to_bytes())?; + w.write_all(&instance.nf_old.to_bytes())?; + w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; + w.write_all(&instance.cmx.to_bytes())?; + w.write_all(&[ + u8::from(instance.enable_spend), + u8::from(instance.enable_output), + u8::from(instance.enable_zsa), + ])?; + + w.write_all(proof.as_ref())?; + Ok(()) + } + + fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { + let read_32_bytes = |r: &mut R| { + let mut ret = [0u8; 32]; + r.read_exact(&mut ret).unwrap(); + ret + }; + let read_bool = |r: &mut R| { + let mut byte = [0u8; 1]; + r.read_exact(&mut byte).unwrap(); + match byte { + [0] => false, + [1] => true, + _ => panic!("Unexpected non-boolean byte"), + } + }; + + let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); + let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let rk = read_32_bytes(&mut r).try_into().unwrap(); + let cmx = + crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let enable_spend = read_bool(&mut r); + let enable_output = read_bool(&mut r); + let enable_zsa = read_bool(&mut r); + let instance = Instance::from_parts( + anchor, + cv_net, + nf_old, + rk, + cmx, + Flags::from_parts(enable_spend, enable_output, enable_zsa), + ); + + let mut proof_bytes = vec![]; + r.read_to_end(&mut proof_bytes)?; + let proof = Proof::new(proof_bytes); + + Ok((instance, proof)) + } + + if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let mut rng = OsRng; + + let (circuit, instance) = generate_dummy_circuit_instance(OsRng); + let instances = &[instance.clone()]; + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, instances).is_ok()); + + let file = std::fs::File::create("src/circuit/circuit_proof_test_case_zsa.bin")?; + write_test_case(file, &instance, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let (instance, proof) = { + let test_case_bytes = fs::read("src/circuit/circuit_proof_test_case_zsa.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + assert_eq!(proof.0.len(), 5120); + + assert!(proof.verify(&vk, &[instance]).is_ok()); + } + + #[cfg(feature = "dev-graph")] + #[test] + fn print_action_circuit() { + use plotters::prelude::*; + + let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root + .titled("Orchard Action Circuit", ("sans-serif", 60)) + .unwrap(); + + let circuit = OrchardCircuitZSA { + witnesses: Witnesses::default(), + phantom: std::marker::PhantomData, + }; + halo2_proofs::dev::CircuitLayout::default() + .show_labels(false) + .view_height(0..(1 << 11)) + .render(K, &circuit, &root) + .unwrap(); + } + + fn check_proof_of_orchard_circuit( + circuit: &OrchardCircuitZSA, + instance: &Instance, + should_pass: bool, + ) { + let proof_verify = MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect(), + ) + .unwrap() + .verify(); + if should_pass { + assert!(proof_verify.is_ok()); + } else { + assert!(proof_verify.is_err()); + } + } + + fn generate_circuit_instance( + is_native_asset: bool, + split_flag: bool, + mut rng: R, + ) -> (OrchardCircuitZSA, Instance) { + // Create asset + let asset_base = if is_native_asset { + AssetBase::native() + } else { + AssetBase::random() + }; + + // Create spent_note + let (spent_note_fvk, spent_note) = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + let nf_old = Nullifier::dummy(&mut rng); + let rho = Rho::from_nf_old(nf_old); + let note = Note::new( + sender_address, + NoteValue::from_raw(40), + asset_base, + rho, + &mut rng, + ); + let spent_note = if split_flag { + note.create_split_note(&mut rng) + } else { + note + }; + (fvk, spent_note) + }; + + let output_value = NoteValue::from_raw(10); + + let (scope, v_net) = if split_flag { + ( + Scope::External, + // Split notes do not contribute to v_net. + // Therefore, if split_flag is true, v_net = - output_value + NoteValue::zero() - output_value, + ) + } else { + ( + spent_note_fvk + .scope_for_address(&spent_note.recipient()) + .unwrap(), + spent_note.value() - output_value, + ) + }; + + let nf_old = spent_note.nullifier(&spent_note_fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = spent_note_fvk.clone().into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let output_note = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + + Note::new(sender_address, output_value, asset_base, rho, &mut rng) + }; + + let cmx = output_note.commitment().into(); + + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(v_net, rcv, asset_base); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let spend_info = SpendInfo { + dummy_sk: None, + fvk: spent_note_fvk, + scope, + note: spent_note, + merkle_path: path, + split_flag, + }; + + ( + OrchardCircuitZSA { + witnesses: Witnesses::from_action_context_unchecked( + spend_info, + output_note, + alpha, + rcv, + ), + phantom: std::marker::PhantomData, + }, + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: true, + }, + ) + } + + fn random_note_commitment(mut rng: impl RngCore) -> NoteCommitment { + NoteCommitment::derive( + pallas::Point::random(&mut rng).to_affine().to_bytes(), + pallas::Point::random(&mut rng).to_affine().to_bytes(), + NoteValue::from_raw(rng.next_u64()), + AssetBase::random(), + pallas::Base::random(&mut rng), + pallas::Base::random(&mut rng), + NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)), + ) + .unwrap() + } + + #[test] + fn orchard_circuit_negative_test() { + let mut rng = OsRng; + + for is_native_asset in [true, false] { + for split_flag in [true, false] { + let (circuit, instance) = + generate_circuit_instance(is_native_asset, split_flag, &mut rng); + + let should_pass = !(matches!((is_native_asset, split_flag), (true, true))); + + check_proof_of_orchard_circuit(&circuit, &instance, should_pass); + + // Set cv_net to be zero + // The proof should fail + let instance_wrong_cv_net = Instance { + anchor: instance.anchor, + cv_net: ValueCommitment::from_bytes(&[0u8; 32]).unwrap(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); + + // Set rk_pub to be a dummy VerificationKey + // The proof should fail + let instance_wrong_rk = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: VerificationKey::dummy(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); + + // Set cm_old to be a random NoteCommitment + // The proof should fail + let circuit_wrong_cm_old = OrchardCircuitZSA { + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: Value::known(random_note_commitment(&mut rng)), + psi_nf: circuit.witnesses.psi_nf, + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, + phantom: std::marker::PhantomData, + }; + check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); + + // Set cmx_pub to be a random NoteCommitment + // The proof should fail + let instance_wrong_cmx_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: random_note_commitment(&mut rng).into(), + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); + + // Set nf_old_pub to be a random Nullifier + // The proof should fail + let instance_wrong_nf_old_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: Nullifier::dummy(&mut rng), + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); + + // If split_flag = 0 , set psi_nf to be a random Pallas base element + // The proof should fail + if !split_flag { + let circuit_wrong_psi_nf = OrchardCircuitZSA { + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: circuit.witnesses.cm_old.clone(), + psi_nf: Value::known(pallas::Base::random(&mut rng)), + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, + phantom: std::marker::PhantomData, + }; + check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); + } + + // If asset is not equal to the native asset, set enable_zsa = 0 + // The proof should fail + if !is_native_asset { + let instance_wrong_enable_zsa = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: false, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_enable_zsa, false); + } + } + } + } +} diff --git a/src/circuit/commit_ivk.rs b/src/circuit/commit_ivk.rs index 33692a4a8..95c9f7746 100644 --- a/src/circuit/commit_ivk.rs +++ b/src/circuit/commit_ivk.rs @@ -1,3 +1,5 @@ +//! Commit IVK (Incoming Viewing Key) for the Orchard circuit. + use core::iter; use group::ff::{Field, PrimeField}; @@ -8,10 +10,10 @@ use halo2_proofs::{ }; use pasta_curves::pallas; -use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}; +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, T_P}; use halo2_gadgets::{ ecc::{chip::EccChip, ScalarFixed, X}, - sinsemilla::{chip::SinsemillaChip, CommitDomain, Message, MessagePiece}, + sinsemilla::{CommitDomain, Message, MessagePiece}, utilities::{bool_check, RangeConstrained}, }; @@ -228,29 +230,29 @@ impl CommitIvkChip { } pub(in crate::circuit) mod gadgets { - use halo2_gadgets::utilities::{lookup_range_check::LookupRangeCheckConfig, RangeConstrained}; - use halo2_proofs::circuit::Chip; + use halo2_gadgets::utilities::{lookup_range_check::PallasLookupRangeCheck, RangeConstrained}; use super::*; + use super::super::orchard_sinsemilla_chip::OrchardSinsemillaChip; + /// `Commit^ivk` from [Section 5.4.8.4 Sinsemilla commitments]. /// /// [Section 5.4.8.4 Sinsemilla commitments]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillacommit #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(in crate::circuit) fn commit_ivk( - sinsemilla_chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >, - ecc_chip: EccChip, + pub(in crate::circuit) fn commit_ivk< + Lookup: PallasLookupRangeCheck, + Chip: OrchardSinsemillaChip, + >( + sinsemilla_chip: Chip, + ecc_chip: EccChip, commit_ivk_chip: CommitIvkChip, mut layouter: impl Layouter, ak: AssignedCell, nk: AssignedCell, - rivk: ScalarFixed>, - ) -> Result>, Error> { + rivk: ScalarFixed>, + ) -> Result>, Error> { let lookup_config = sinsemilla_chip.config().lookup_config(); // We need to hash `ak || nk` where each of `ak`, `nk` is a field element (255 bits). @@ -398,8 +400,8 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:commit-ivk-canonicity-ak?partial). #[allow(clippy::type_complexity)] - fn ak_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn ak_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, a: AssignedCell, ) -> Result< @@ -439,8 +441,8 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:commit-ivk-canonicity-nk?partial). #[allow(clippy::type_complexity)] - fn nk_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn nk_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, b_2: &RangeConstrained>, c: AssignedCell, @@ -664,6 +666,7 @@ mod tests { use core::iter; use super::{gadgets, CommitIvkChip, CommitIvkConfig}; + use crate::constants::{ fixed_bases::COMMIT_IVK_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, L_ORCHARD_BASE, T_Q, @@ -678,7 +681,13 @@ mod tests { chip::{SinsemillaChip, SinsemillaConfig}, primitives::CommitDomain, }, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::{ + lookup_range_check::{ + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, + PallasLookupRangeCheckConfig, + }, + UtilitiesInstructions, + }, }; use halo2_proofs::{ circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, @@ -688,209 +697,236 @@ mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - #[test] - fn commit_ivk() { - #[derive(Default)] - struct MyCircuit { - ak: Value, - nk: Value, - } + trait MyLookup: PallasLookupRangeCheck { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool; + } + + impl MyLookup for PallasLookupRangeCheckConfig { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool = false; + } + + impl MyLookup for PallasLookupRangeCheck4_5BConfig { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool = true; + } - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; + #[derive(Default)] + struct MyCircuit { + ak: Value, + nk: Value, + phantom: std::marker::PhantomData, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = ( + SinsemillaConfig, + CommitIvkConfig, + EccConfig, + ); + + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self { + ak: Default::default(), + nk: Default::default(), + phantom: std::marker::PhantomData, + } } - impl Circuit for MyCircuit { - type Config = ( - SinsemillaConfig, - CommitIvkConfig, - EccConfig, + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + let range_check = Lookup::configure(meta, advices[9], table_idx); + let sinsemilla_config = SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + Lookup, + >::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + Lookup::ENABLE_HASH_FROM_PRIVATE_POINT, ); - type FloorPlanner = SimpleFloorPlanner; - fn without_witnesses(&self) -> Self { - Self::default() - } + let commit_ivk_config = CommitIvkChip::configure(meta, advices); - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - for advice in advices.iter() { - meta.enable_equality(*advice); - } + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + (sinsemilla_config, commit_ivk_config, ecc_config) + } - let table_idx = meta.lookup_table_column(); - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let sinsemilla_config = SinsemillaChip::< + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (sinsemilla_config, commit_ivk_config, ecc_config) = config; + + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::< OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - >::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - ); - - let commit_ivk_config = CommitIvkChip::configure(meta, advices); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - (sinsemilla_config, commit_ivk_config, ecc_config) - } + Lookup, + >::load(sinsemilla_config.clone(), &mut layouter)?; - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let (sinsemilla_config, commit_ivk_config, ecc_config) = config; - - // Load the Sinsemilla generator lookup table used by the whole circuit. - SinsemillaChip::::load(sinsemilla_config.clone(), &mut layouter)?; - - // Construct a Sinsemilla chip - let sinsemilla_chip = SinsemillaChip::construct(sinsemilla_config); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(ecc_config); - - let commit_ivk_chip = CommitIvkChip::construct(commit_ivk_config.clone()); - - // Witness ak - let ak = self.load_private( - layouter.namespace(|| "load ak"), - commit_ivk_config.advices[0], - self.ak, - )?; - - // Witness nk - let nk = self.load_private( - layouter.namespace(|| "load nk"), - commit_ivk_config.advices[0], - self.nk, - )?; - - // Use a random scalar for rivk - let rivk = pallas::Scalar::random(OsRng); - let rivk_gadget = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rivk"), - Value::known(rivk), - )?; - - let ivk = gadgets::commit_ivk( - sinsemilla_chip, - ecc_chip, - commit_ivk_chip, - layouter.namespace(|| "CommitIvk"), - ak, - nk, - rivk_gadget, - )?; - - self.ak - .zip(self.nk) - .zip(ivk.inner().value()) - .assert_if_known(|((ak, nk), ivk)| { - let expected_ivk = { - let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); - // Hash ak || nk - domain - .short_commit( - iter::empty() - .chain( - ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain( - nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ), - &rivk, - ) - .unwrap() - }; - - &&expected_ivk == ivk - }); + // Construct a Sinsemilla chip + let sinsemilla_chip = SinsemillaChip::construct(sinsemilla_config); - Ok(()) - } + // Construct an ECC chip + let ecc_chip = EccChip::construct(ecc_config); + + let commit_ivk_chip = CommitIvkChip::construct(commit_ivk_config.clone()); + + // Witness ak + let ak = self.load_private( + layouter.namespace(|| "load ak"), + commit_ivk_config.advices[0], + self.ak, + )?; + + // Witness nk + let nk = self.load_private( + layouter.namespace(|| "load nk"), + commit_ivk_config.advices[0], + self.nk, + )?; + + // Use a random scalar for rivk + let rivk = pallas::Scalar::random(OsRng); + let rivk_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + Value::known(rivk), + )?; + + let ivk = gadgets::commit_ivk( + sinsemilla_chip, + ecc_chip, + commit_ivk_chip, + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk_gadget, + )?; + + self.ak + .zip(self.nk) + .zip(ivk.inner().value()) + .assert_if_known(|((ak, nk), ivk)| { + let expected_ivk = { + let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); + // Hash ak || nk + domain + .short_commit( + iter::empty() + .chain(ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)) + .chain(nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)), + &rivk, + ) + .unwrap() + }; + + &&expected_ivk == ivk + }); + + Ok(()) } + } + fn commit_ivk() { let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); // Test different values of `ak`, `nk` let circuits = [ // `ak` = 0, `nk` = 0 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::zero()), nk: Value::known(pallas::Base::zero()), + phantom: std::marker::PhantomData, }, // `ak` = T_Q - 1, `nk` = T_Q - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(T_Q - 1)), nk: Value::known(pallas::Base::from_u128(T_Q - 1)), + phantom: std::marker::PhantomData, }, // `ak` = T_Q, `nk` = T_Q - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(T_Q)), nk: Value::known(pallas::Base::from_u128(T_Q)), + phantom: std::marker::PhantomData, }, // `ak` = 2^127 - 1, `nk` = 2^127 - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128((1 << 127) - 1)), nk: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + phantom: std::marker::PhantomData, }, // `ak` = 2^127, `nk` = 2^127 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(1 << 127)), nk: Value::known(pallas::Base::from_u128(1 << 127)), + phantom: std::marker::PhantomData, }, // `ak` = 2^254 - 1, `nk` = 2^254 - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(two_pow_254 - pallas::Base::one()), nk: Value::known(two_pow_254 - pallas::Base::one()), + phantom: std::marker::PhantomData, }, // `ak` = 2^254, `nk` = 2^254 - MyCircuit { + MyCircuit:: { ak: Value::known(two_pow_254), nk: Value::known(two_pow_254), + phantom: std::marker::PhantomData, }, ]; @@ -899,4 +935,14 @@ mod tests { assert_eq!(prover.verify(), Ok(())); } } + + #[test] + fn commit_ivk_vanilla() { + commit_ivk::() + } + + #[test] + fn commit_ivk_zsa() { + commit_ivk::() + } } diff --git a/src/circuit/derive_nullifier.rs b/src/circuit/derive_nullifier.rs new file mode 100644 index 000000000..f2f65517a --- /dev/null +++ b/src/circuit/derive_nullifier.rs @@ -0,0 +1,112 @@ +//! Derive nullifier logic for the Orchard circuit. + +use crate::constants::nullifier_l::nullifier_l; +use halo2_gadgets::utilities::cond_swap::CondSwapChip; +use halo2_proofs::circuit::AssignedCell; +use pasta_curves::pallas; + +pub struct ZsaNullifierParams { + pub cond_swap_chip: CondSwapChip, + pub split_flag: AssignedCell, +} + +pub(in crate::circuit) mod gadgets { + use super::*; + + use crate::{ + circuit::gadget::AddInstruction, + constants::{NullifierK, OrchardFixedBases}, + }; + use halo2_gadgets::{ + ecc::{chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, + poseidon::{ + primitives::{self as poseidon, ConstantLength}, + Hash as PoseidonHash, PoseidonSpongeInstructions, + }, + }; + use halo2_proofs::{circuit::Layouter, plonk}; + + /// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. + /// + /// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers + #[allow(clippy::too_many_arguments)] + pub(in crate::circuit) fn derive_nullifier< + PoseidonChip: PoseidonSpongeInstructions, 3, 2>, + AddChip: AddInstruction, + EccChip: EccInstructions< + pallas::Affine, + FixedPoints = OrchardFixedBases, + Point = EccPoint, + Var = AssignedCell, + >, + >( + layouter: &mut impl Layouter, + poseidon_chip: PoseidonChip, + add_chip: AddChip, + ecc_chip: EccChip, + rho: AssignedCell, + psi: &AssignedCell, + cm: &Point, + nk: AssignedCell, + zsa_params: Option, + ) -> Result, plonk::Error> { + // hash = poseidon_hash(nk, rho) + let hash = { + let poseidon_message = [nk, rho]; + let poseidon_hasher = + PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; + poseidon_hasher.hash( + layouter.namespace(|| "Poseidon hash (nk, rho)"), + poseidon_message, + )? + }; + + // Add hash output to psi. + // `scalar` = poseidon_hash(nk, rho) + psi. + let scalar = add_chip.add( + layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), + &hash, + psi, + )?; + + // Multiply scalar by NullifierK + // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. + let product = { + let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); + nullifier_k.mul( + layouter.namespace(|| "[poseidon_output + psi] NullifierK"), + scalar, + )? + }; + + // Add cm to multiplied fixed base + // nf = cm + [poseidon_output + psi] NullifierK + let nf = cm.add(layouter.namespace(|| "nf"), &product)?; + + match zsa_params { + None => Ok(nf.extract_p()), + Some(zsa_params) => { + // Add NullifierL to nf + // split_note_nf = NullifierL + nf + let nullifier_l = Point::new_from_constant( + ecc_chip.clone(), + layouter.namespace(|| "witness NullifierL constant"), + nullifier_l(), + )?; + let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; + + // Select the desired nullifier according to split_flag + Ok(Point::from_inner( + ecc_chip, + zsa_params.cond_swap_chip.mux_on_points( + layouter.namespace(|| "mux on nf"), + &zsa_params.split_flag, + nf.inner(), + split_note_nf.inner(), + )?, + ) + .extract_p()) + } + } + } +} diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 12c3c90e6..2675fef13 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,32 +1,39 @@ -//! Gadgets used in the Orchard circuit. +//! Common gadgets and functions used in the Orchard circuit. use ff::Field; -use pasta_curves::pallas; - -use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; -use crate::constants::{ - NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - ValueCommitV, -}; use halo2_gadgets::{ - ecc::{ - chip::EccChip, EccInstructions, FixedPoint, FixedPointBaseField, FixedPointShort, Point, - ScalarFixed, ScalarFixedShort, X, - }, - poseidon::{ - primitives::{self as poseidon, ConstantLength}, - Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, - }, + ecc::chip::EccChip, + poseidon::Pow5Chip as PoseidonChip, sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, + utilities::{cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck}, +}; +use pasta_curves::pallas; + +use crate::{ + circuit::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, Config}, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, }; use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, + circuit::Value, + circuit::{AssignedCell, Chip, Layouter}, plonk::{self, Advice, Assigned, Column}, }; pub(in crate::circuit) mod add_chip; -impl super::Config { +/// An instruction set for adding two circuit words (field elements). +pub(in crate::circuit) trait AddInstruction: Chip { + /// Constraints `a + b` and returns the sum. + fn add( + &self, + layouter: impl Layouter, + a: &AssignedCell, + b: &AssignedCell, + ) -> Result, plonk::Error>; +} + +impl Config { pub(super) fn add_chip(&self) -> add_chip::AddChip { add_chip::AddChip::construct(self.add_config.clone()) } @@ -35,31 +42,31 @@ impl super::Config { CommitIvkChip::construct(self.commit_ivk_config.clone()) } - pub(super) fn ecc_chip(&self) -> EccChip { + pub(super) fn ecc_chip(&self) -> EccChip { EccChip::construct(self.ecc_config.clone()) } pub(super) fn sinsemilla_chip_1( &self, - ) -> SinsemillaChip { + ) -> SinsemillaChip { SinsemillaChip::construct(self.sinsemilla_config_1.clone()) } pub(super) fn sinsemilla_chip_2( &self, - ) -> SinsemillaChip { + ) -> SinsemillaChip { SinsemillaChip::construct(self.sinsemilla_config_2.clone()) } pub(super) fn merkle_chip_1( &self, - ) -> MerkleChip { + ) -> MerkleChip { MerkleChip::construct(self.merkle_config_1.clone()) } pub(super) fn merkle_chip_2( &self, - ) -> MerkleChip { + ) -> MerkleChip { MerkleChip::construct(self.merkle_config_2.clone()) } @@ -67,24 +74,17 @@ impl super::Config { PoseidonChip::construct(self.poseidon_config.clone()) } - pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { + pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { NoteCommitChip::construct(self.new_note_commit_config.clone()) } - pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { + pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { NoteCommitChip::construct(self.old_note_commit_config.clone()) } -} -/// An instruction set for adding two circuit words (field elements). -pub(in crate::circuit) trait AddInstruction: Chip { - /// Constraints `a + b` and returns the sum. - fn add( - &self, - layouter: impl Layouter, - a: &AssignedCell, - b: &AssignedCell, - ) -> Result, plonk::Error>; + pub(super) fn cond_swap_chip(&self) -> CondSwapChip { + CondSwapChip::construct(self.merkle_config_1.cond_swap_config.clone()) + } } /// Witnesses the given value in a standalone region. @@ -106,98 +106,46 @@ where ) } -/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. -/// -/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit -pub(in crate::circuit) fn value_commit_orchard< - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - ecc_chip: EccChip, - v: ScalarFixedShort, - rcv: ScalarFixed, -) -> Result, plonk::Error> { - // commitment = [v] ValueCommitV - let (commitment, _) = { - let value_commit_v = ValueCommitV; - let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); - value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v)? - }; - - // blind = [rcv] ValueCommitR - let (blind, _rcv) = { - let value_commit_r = OrchardFixedBasesFull::ValueCommitR; - let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); - - // [rcv] ValueCommitR - value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? - }; - - // [v] ValueCommitV + [rcv] ValueCommitR - commitment.add(layouter.namespace(|| "cv"), &blind) +/// Witnesses is_native_asset. +pub(in crate::circuit) fn assign_is_native_asset( + layouter: impl Layouter, + column: Column, + asset: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + asset.map(|asset| { + if bool::from(asset.is_native()) { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) } -/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. -/// -/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers -#[allow(clippy::too_many_arguments)] -pub(in crate::circuit) fn derive_nullifier< - PoseidonChip: PoseidonSpongeInstructions, 3, 2>, - AddChip: AddInstruction, - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - poseidon_chip: PoseidonChip, - add_chip: AddChip, - ecc_chip: EccChip, - rho: AssignedCell, - psi: &AssignedCell, - cm: &Point, - nk: AssignedCell, -) -> Result, plonk::Error> { - // hash = poseidon_hash(nk, rho) - let hash = { - let poseidon_message = [nk, rho]; - let poseidon_hasher = - PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; - poseidon_hasher.hash( - layouter.namespace(|| "Poseidon hash (nk, rho)"), - poseidon_message, - )? - }; - - // Add hash output to psi. - // `scalar` = poseidon_hash(nk, rho) + psi. - let scalar = add_chip.add( - layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), - &hash, - psi, - )?; - - // Multiply scalar by NullifierK - // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. - // - let product = { - let nullifier_k = FixedPointBaseField::from_inner(ecc_chip, NullifierK); - nullifier_k.mul( - layouter.namespace(|| "[poseidon_output + psi] NullifierK"), - scalar, - )? - }; - - // Add cm to multiplied fixed base to get nf - // cm + [poseidon_output + psi] NullifierK - cm.add(layouter.namespace(|| "nf"), &product) - .map(|res| res.extract_p()) +/// Witnesses split_flag. +pub(in crate::circuit) fn assign_split_flag( + layouter: impl Layouter, + column: Column, + split_flag: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + split_flag.map(|split_flag| { + if split_flag { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) } - -pub(in crate::circuit) use crate::circuit::commit_ivk::gadgets::commit_ivk; -pub(in crate::circuit) use crate::circuit::note_commit::gadgets::note_commit; diff --git a/src/circuit/gadget/add_chip.rs b/src/circuit/gadget/add_chip.rs index 0973a3f3b..9c0fb5dad 100644 --- a/src/circuit/gadget/add_chip.rs +++ b/src/circuit/gadget/add_chip.rs @@ -1,3 +1,5 @@ +//! 'Add' chip implemetation. + use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, plonk::{self, Advice, Column, ConstraintSystem, Constraints, Selector}, diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index 9daa685f2..849ffc378 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -1,34 +1,35 @@ -use core::iter; - -use group::ff::PrimeField; -use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, - poly::Rotation, -}; -use pasta_curves::pallas; +//! Note commitment logic for the Orchard circuit. use crate::{ constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, value::NoteValue, }; +use group::ff::PrimeField; use halo2_gadgets::{ ecc::{ chip::{EccChip, NonIdentityEccPoint}, - Point, ScalarFixed, + {NonIdentityPoint, Point, ScalarFixed}, }, sinsemilla::{ chip::{SinsemillaChip, SinsemillaConfig}, CommitDomain, Message, MessagePiece, }, utilities::{ - bool_check, lookup_range_check::LookupRangeCheckConfig, FieldValue, RangeConstrained, + bool_check, cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck, + FieldValue, RangeConstrained, }, }; +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, + poly::Rotation, +}; +use pasta_curves::pallas; +use std::iter; -type NoteCommitPiece = MessagePiece< +type NoteCommitPiece = MessagePiece< pallas::Affine, - SinsemillaChip, + SinsemillaChip, 10, 253, >; @@ -63,14 +64,15 @@ type CanonicityBounds = ( /// /// #[derive(Clone, Debug)] -struct DecomposeB { +struct DecomposeB { q_notecommit_b: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeB { +impl DecomposeB { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -115,19 +117,20 @@ impl DecomposeB { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, RangeConstrained>, @@ -169,7 +172,7 @@ impl DecomposeB { fn assign( &self, layouter: &mut impl Layouter, - b: NoteCommitPiece, + b: NoteCommitPiece, b_0: RangeConstrained>, b_1: RangeConstrained>, b_2: RangeConstrained>, @@ -208,14 +211,15 @@ impl DecomposeB { /// /// #[derive(Clone, Debug)] -struct DecomposeD { +struct DecomposeD { q_notecommit_d: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeD { +impl DecomposeD { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -260,19 +264,20 @@ impl DecomposeD { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, value: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, RangeConstrained>, @@ -308,7 +313,7 @@ impl DecomposeD { fn assign( &self, layouter: &mut impl Layouter, - d: NoteCommitPiece, + d: NoteCommitPiece, d_0: RangeConstrained>, d_1: RangeConstrained>, d_2: RangeConstrained>, @@ -344,14 +349,15 @@ impl DecomposeD { /// /// #[derive(Clone, Debug)] -struct DecomposeE { +struct DecomposeE { q_notecommit_e: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeE { +impl DecomposeE { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -382,19 +388,20 @@ impl DecomposeE { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, value: &AssignedCell, rho: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -430,7 +437,7 @@ impl DecomposeE { fn assign( &self, layouter: &mut impl Layouter, - e: NoteCommitPiece, + e: NoteCommitPiece, e_0: RangeConstrained>, e_1: RangeConstrained>, ) -> Result<(), Error> { @@ -463,13 +470,14 @@ impl DecomposeE { /// /// #[derive(Clone, Debug)] -struct DecomposeG { +struct DecomposeG { q_notecommit_g: Selector, col_l: Column, col_m: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeG { +impl DecomposeG { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -507,19 +515,20 @@ impl DecomposeG { q_notecommit_g, col_l, col_m, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, rho: &AssignedCell, psi: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -551,7 +560,7 @@ impl DecomposeG { fn assign( &self, layouter: &mut impl Layouter, - g: NoteCommitPiece, + g: NoteCommitPiece, g_0: RangeConstrained>, g_1: RangeConstrained>, z1_g: AssignedCell, @@ -576,6 +585,7 @@ impl DecomposeG { } } +/// For Vanilla Orchard circuit, /// h = h_0 || h_1 || h_2 /// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits /// @@ -585,14 +595,15 @@ impl DecomposeG { /// /// #[derive(Clone, Debug)] -struct DecomposeH { +struct DecomposeHVanilla { q_notecommit_h: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeH { +impl DecomposeHVanilla { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -629,18 +640,19 @@ impl DecomposeH { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, psi: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -673,7 +685,7 @@ impl DecomposeH { fn assign( &self, layouter: &mut impl Layouter, - h: NoteCommitPiece, + h: NoteCommitPiece, h_0: RangeConstrained>, h_1: RangeConstrained>, ) -> Result, Error> { @@ -695,6 +707,282 @@ impl DecomposeH { } } +/// For ZSA Orchard circuit, +/// h_zec = h_0 || h_1 || h_2_zec +/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits +/// +/// h_zsa = h_0 || h_1 || h_2_zsa +/// = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_h | +/// -------------------------------------------- +/// | h_zec | h_0 | h_1 | 1 | +/// | h_zsa | h_2_zsa | | 0 | +#[derive(Clone, Debug)] +struct DecomposeHZsa { + q_notecommit_h: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + _lookup_marker: std::marker::PhantomData, +} + +impl DecomposeHZsa { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two_pow_5: pallas::Base, + two_pow_6: pallas::Base, + ) -> Self { + let q_notecommit_h = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece h", |meta| { + let q_notecommit_h = meta.query_selector(q_notecommit_h); + + // h_zec has been constrained to 10 bits by the Sinsemilla hash. + let h_zec = meta.query_advice(col_l, Rotation::cur()); + // h_0 has been constrained to be 5 bits outside this gate. + let h_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains h_1 to be boolean. + let h_1 = meta.query_advice(col_r, Rotation::cur()); + + // h_zsa has been constrained to 10 bits by the Sinsemilla hash. + let h_zsa = meta.query_advice(col_l, Rotation::next()); + // h_2_zsa has been constrained to be 4 bits outside this gate. + let h_2_zsa = meta.query_advice(col_m, Rotation::next()); + + // h_zec = h_0 + (2^5) h_1 + let zec_decomposition_check = h_zec - (h_0.clone() + h_1.clone() * two_pow_5); + + // h_zsa = h_0 + (2^5) h_1 + (2^6) h_2_zsa + let zsa_decomposition_check = + h_zsa - (h_0 + h_1.clone() * two_pow_5 + h_2_zsa * two_pow_6); + + Constraints::with_selector( + q_notecommit_h, + [ + ("bool_check h_1", bool_check(h_1)), + ("zec_decomposition", zec_decomposition_check), + ("zsa_decomposition", zsa_decomposition_check), + ], + ) + }); + + Self { + q_notecommit_h, + col_l, + col_m, + col_r, + _lookup_marker: std::marker::PhantomData, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &Lookup, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + psi: &AssignedCell, + asset: &NonIdentityEccPoint, + ) -> Result< + ( + NoteCommitPiece, + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // Constrain h_0 to be 5 bits. + let h_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "h_0"), + psi.value(), + 249..254, + )?; + + // h_1 will be boolean-constrained in the gate. + let h_1 = RangeConstrained::bitrange_of(psi.value(), 254..255); + + // Constrain h_2_zsa to be 4 bits. + let h_2_zsa = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "h_2_zsa"), + asset.x().value(), + 0..4, + )?; + + let h_zec = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "h_zec"), + [ + h_0.value(), + h_1, + RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..4), + ], + )?; + + let h_zsa = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "h_zsa"), + [h_0.value(), h_1, h_2_zsa.value()], + )?; + + Ok((h_zec, h_zsa, h_0, h_1, h_2_zsa)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + h_zec: NoteCommitPiece, + h_zsa: NoteCommitPiece, + h_0: RangeConstrained>, + h_1: RangeConstrained>, + h_2_zsa: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece h", + |mut region| { + self.q_notecommit_h.enable(&mut region, 0)?; + + h_zec + .inner() + .cell_value() + .copy_advice(|| "h_zec", &mut region, self.col_l, 0)?; + h_0.inner() + .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; + let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; + + h_zsa + .inner() + .cell_value() + .copy_advice(|| "h_zsa", &mut region, self.col_l, 1)?; + + h_2_zsa + .inner() + .copy_advice(|| "h_2_zsa", &mut region, self.col_m, 1)?; + + Ok(h_1) + }, + ) + } +} + +/// j = j_0 || j_1 +/// = (bit 254 of x(asset)) || (ỹ bit of asset) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_j | +/// ------------------------------------ +/// | j | j_0 | j_1 | 1 | +#[derive(Clone, Debug)] +struct DecomposeJ { + q_notecommit_j: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + _lookup_marker: std::marker::PhantomData, +} + +impl DecomposeJ { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two: pallas::Base, + ) -> Self { + let q_notecommit_j = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece j", |meta| { + let q_notecommit_j = meta.query_selector(q_notecommit_j); + + // j has been constrained to 10 bits by the Sinsemilla hash. + let j = meta.query_advice(col_l, Rotation::cur()); + // This gate constrains j_0 to be boolean. + let j_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains j_1 to be boolean. + let j_1 = meta.query_advice(col_r, Rotation::cur()); + + // j = j_0 + (2) j_1 + let decomposition_check = j - (j_0.clone() + j_1.clone() * two); + + Constraints::with_selector( + q_notecommit_j, + [ + ("bool_check j_0", bool_check(j_0)), + ("bool_check j_1", bool_check(j_1)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_j, + col_l, + col_m, + col_r, + _lookup_marker: std::marker::PhantomData, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + chip: SinsemillaChip, + layouter: &mut impl Layouter, + asset: &NonIdentityEccPoint, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // j_0, j_1 will be boolean-constrained in the gate. + let j_0 = RangeConstrained::bitrange_of(asset.x().value(), 254..255); + let j_1 = RangeConstrained::bitrange_of(asset.y().value(), 0..1); + + let j = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "j"), + [ + j_0, + j_1, + RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..8), + ], + )?; + + Ok((j, j_0, j_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + j: NoteCommitPiece, + j_0: RangeConstrained>, + j_1: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece j", + |mut region| { + self.q_notecommit_j.enable(&mut region, 0)?; + + j.inner() + .cell_value() + .copy_advice(|| "j", &mut region, self.col_l, 0)?; + let j_0 = region.assign_advice(|| "j_0", self.col_m, 0, || *j_0.inner())?; + j_1.inner() + .copy_advice(|| "j_1", &mut region, self.col_r, 0)?; + + Ok(j_0) + }, + ) + } +} + /// | A_6 | A_7 | A_8 | A_9 | q_notecommit_g_d | /// ----------------------------------------------------------- /// | x(g_d) | b_0 | a | z13_a | 1 | @@ -702,15 +990,16 @@ impl DecomposeH { /// /// #[derive(Clone, Debug)] -struct GdCanonicity { +struct GdCanonicity { q_notecommit_g_d: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl GdCanonicity { +impl GdCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -774,6 +1063,7 @@ impl GdCanonicity { col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } @@ -782,7 +1072,7 @@ impl GdCanonicity { &self, layouter: &mut impl Layouter, g_d: &NonIdentityEccPoint, - a: NoteCommitPiece, + a: NoteCommitPiece, b_0: RangeConstrained>, b_1: AssignedCell, a_prime: AssignedCell, @@ -812,22 +1102,30 @@ impl GdCanonicity { } } -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d | -/// ------------------------------------------------------------------- -/// | x(pk_d) | b_3 | c | z13_c | 1 | -/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | +/// For pk_d +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d_asset | +/// ------------------------------------------------------------------------- +/// | x(pk_d) | b_3 | c | z13_c | 1 | +/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | +/// +/// For asset +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d_asset | +/// ------------------------------------------------------------------------------ +/// | x(asset) | h_2_zsa | i | z13_i | 1 | +/// | | j_0 | h2_i_prime | z14_h2_i_prime | 0 | /// /// #[derive(Clone, Debug)] -struct PkdCanonicity { - q_notecommit_pk_d: Selector, +struct PkdAssetCanonicity { + q_notecommit_pk_d_asset: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl PkdCanonicity { +impl PkdAssetCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -840,10 +1138,13 @@ impl PkdCanonicity { two_pow_254: pallas::Base, t_p: Expression, ) -> Self { - let q_notecommit_pk_d = meta.selector(); + let q_notecommit_pk_d_asset = meta.selector(); - meta.create_gate("NoteCommit input pk_d", |meta| { - let q_notecommit_pk_d = meta.query_selector(q_notecommit_pk_d); + meta.create_gate("NoteCommit input pk_d or asset", |meta| { + // The comments and variable names are for `pk_d` + // This gate is also used with `asset`. + // We have just to replace `pk_d`, `b_3`, `c`, `d_0` by `asset`, `h_2_zsa`, `i`, `j_0` + let q_notecommit_pk_d_asset = meta.query_selector(q_notecommit_pk_d_asset); let pkd_x = meta.query_advice(col_l, Rotation::cur()); @@ -876,7 +1177,7 @@ impl PkdCanonicity { .map(move |(name, poly)| (name, d_0.clone() * poly)); Constraints::with_selector( - q_notecommit_pk_d, + q_notecommit_pk_d_asset, iter::empty() .chain(Some(("decomposition", decomposition_check))) .chain(Some(("b3_c_prime_check", b3_c_prime_check))) @@ -885,28 +1186,32 @@ impl PkdCanonicity { }); Self { - q_notecommit_pk_d, + q_notecommit_pk_d_asset, col_l, col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::too_many_arguments)] fn assign( + // This function is used for `pk_d` and `asset`. + // For `pk_d`, inputs are `pk_d`, `b_3`, `c`, `d_0`, `b3_c_prime`, `z13_c`, `z14_b3_c_prime` + // For `asset`, inputs are `asset`, `h_2_zsa`, `i`, `j_0`, `h2_i_prime`, `z13_i`, `z14_h2_i_prime` &self, layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, b_3: RangeConstrained>, - c: NoteCommitPiece, + c: NoteCommitPiece, d_0: AssignedCell, b3_c_prime: AssignedCell, z13_c: AssignedCell, z14_b3_c_prime: AssignedCell, ) -> Result<(), Error> { layouter.assign_region( - || "NoteCommit input pk_d", + || "NoteCommit input pk_d or asset", |mut region| { pk_d.x() .copy_advice(|| "pkd_x", &mut region, self.col_l, 0)?; @@ -923,7 +1228,7 @@ impl PkdCanonicity { z13_c.copy_advice(|| "z13_c", &mut region, self.col_z, 0)?; z14_b3_c_prime.copy_advice(|| "z14_b3_c_prime", &mut region, self.col_z, 1)?; - self.q_notecommit_pk_d.enable(&mut region, 0) + self.q_notecommit_pk_d_asset.enable(&mut region, 0) }, ) } @@ -1013,15 +1318,16 @@ impl ValueCanonicity { /// /// #[derive(Clone, Debug)] -struct RhoCanonicity { +struct RhoCanonicity { q_notecommit_rho: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl RhoCanonicity { +impl RhoCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -1083,6 +1389,7 @@ impl RhoCanonicity { col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } @@ -1092,7 +1399,7 @@ impl RhoCanonicity { layouter: &mut impl Layouter, rho: AssignedCell, e_1: RangeConstrained>, - f: NoteCommitPiece, + f: NoteCommitPiece, g_0: AssignedCell, e1_f_prime: AssignedCell, z13_f: AssignedCell, @@ -1412,29 +1719,46 @@ impl YCanonicity { #[allow(non_snake_case)] #[derive(Clone, Debug)] -pub struct NoteCommitConfig { - b: DecomposeB, - d: DecomposeD, - e: DecomposeE, - g: DecomposeG, - h: DecomposeH, - g_d: GdCanonicity, - pk_d: PkdCanonicity, +pub struct NoteCommitConfig { + b: DecomposeB, + d: DecomposeD, + e: DecomposeE, + g: DecomposeG, + g_d: GdCanonicity, + pk_d_asset: PkdAssetCanonicity, value: ValueCanonicity, - rho: RhoCanonicity, + rho: RhoCanonicity, psi: PsiCanonicity, y_canon: YCanonicity, advices: [Column; 10], sinsemilla_config: - SinsemillaConfig, + SinsemillaConfig, + specific_config_for_circuit: SpecificConfigForCircuit, +} + +#[derive(Clone, Debug)] +pub enum SpecificConfigForCircuit { + Vanilla(NoteCommitConfigForVanillaCircuit), + Zsa(NoteCommitConfigForZsaCircuit), +} + +#[derive(Clone, Debug)] +pub struct NoteCommitConfigForVanillaCircuit { + h_vanilla: DecomposeHVanilla, } #[derive(Clone, Debug)] -pub struct NoteCommitChip { - config: NoteCommitConfig, +pub struct NoteCommitConfigForZsaCircuit { + h_zsa: DecomposeHZsa, + j: DecomposeJ, } -impl NoteCommitChip { +#[derive(Clone, Debug)] +pub struct NoteCommitChip { + pub config: NoteCommitConfig, +} + +impl NoteCommitChip { #[allow(non_snake_case)] #[allow(clippy::many_single_char_names)] pub(in crate::circuit) fn configure( @@ -1444,8 +1768,10 @@ impl NoteCommitChip { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, + Lookup, >, - ) -> NoteCommitConfig { + is_zsa_circuit: bool, + ) -> NoteCommitConfig { // Useful constants let two = pallas::Base::from(2); let two_pow_2 = pallas::Base::from(1 << 2); @@ -1474,7 +1800,14 @@ impl NoteCommitChip { let d = DecomposeD::configure(meta, col_l, col_m, col_r, two, two_pow_2, two_pow_10); let e = DecomposeE::configure(meta, col_l, col_m, col_r, two_pow_6); let g = DecomposeG::configure(meta, col_l, col_m, two, two_pow_10); - let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5); + let specific_config_for_circuit = if is_zsa_circuit { + let h = DecomposeHZsa::configure(meta, col_l, col_m, col_r, two_pow_5, two_pow_6); + let j = DecomposeJ::configure(meta, col_l, col_m, col_r, two); + SpecificConfigForCircuit::Zsa(NoteCommitConfigForZsaCircuit { h_zsa: h, j }) + } else { + let h = DecomposeHVanilla::configure(meta, col_l, col_m, col_r, two_pow_5); + SpecificConfigForCircuit::Vanilla(NoteCommitConfigForVanillaCircuit { h_vanilla: h }) + }; let g_d = GdCanonicity::configure( meta, @@ -1488,7 +1821,7 @@ impl NoteCommitChip { t_p.clone(), ); - let pk_d = PkdCanonicity::configure( + let pk_d_asset = PkdAssetCanonicity::configure( meta, col_l, col_m, @@ -1544,43 +1877,62 @@ impl NoteCommitChip { d, e, g, - h, g_d, - pk_d, + pk_d_asset, value, rho, psi, y_canon, advices, sinsemilla_config, + specific_config_for_circuit, } } - pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { + pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { Self { config } } } -pub(in crate::circuit) mod gadgets { - use halo2_proofs::circuit::{Chip, Value}; +pub struct ZsaNoteCommitParams { + pub cond_swap_chip: CondSwapChip, + pub asset: NonIdentityEccPoint, + pub is_native_asset: AssignedCell, +} +pub struct ZsaFinalDecomposition { + pub h_zsa: NoteCommitPiece, + pub h_2_zsa: RangeConstrained>, + pub i: NoteCommitPiece, + pub j: NoteCommitPiece, + pub j_0: RangeConstrained>, + pub j_1: RangeConstrained>, +} +pub(in crate::circuit) mod gadgets { use super::*; #[allow(clippy::many_single_char_names)] #[allow(clippy::type_complexity)] #[allow(clippy::too_many_arguments)] - pub(in crate::circuit) fn note_commit( + pub(in crate::circuit) fn note_commit( mut layouter: impl Layouter, - chip: SinsemillaChip, - ecc_chip: EccChip, - note_commit_chip: NoteCommitChip, + chip: SinsemillaChip, + ecc_chip: EccChip, + note_commit_chip: NoteCommitChip, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, value: AssignedCell, rho: AssignedCell, psi: AssignedCell, - rcm: ScalarFixed>, - ) -> Result>, Error> { + rcm: ScalarFixed>, + zsa_params: Option, + ) -> Result>, Error> { + match (&zsa_params, ¬e_commit_chip.config.specific_config_for_circuit) { + (Some(_), SpecificConfigForCircuit::Zsa(_)) => {}, + (None, SpecificConfigForCircuit::Vanilla(_)) => {}, + _ => panic!("ZSA parameters must be provided for ZSA circuits, and must not be provided for vanilla circuits"), + } + let lookup_config = chip.config().lookup_config(); // `a` = bits 0..=249 of `x(g_d)` @@ -1623,10 +1975,69 @@ pub(in crate::circuit) mod gadgets { let (g, g_0, g_1) = DecomposeG::decompose(&lookup_config, chip.clone(), &mut layouter, &rho, &psi)?; - // h = h_0 || h_1 || h_2 - // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits - let (h, h_0, h_1) = - DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi)?; + let (h_zec, h_0, h_1, zsa_decomposition) = match &zsa_params { + None => { + // h_zec = h_0 || h_1 || h_2 + // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits + let (h_zec, h_0, h_1) = DecomposeHVanilla::decompose( + &lookup_config, + chip.clone(), + &mut layouter, + &psi, + )?; + (h_zec, h_0, h_1, None) + } + Some(zsa_params) => { + // h_zec = h_0 || h_1 || h_2_zec + // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits + // h_zsa = h_0 || h_1 || h_2_zsa + // = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) + let (h_zec, h_zsa, h_0, h_1, h_2_zsa) = DecomposeHZsa::decompose( + &lookup_config, + chip.clone(), + &mut layouter, + &psi, + &zsa_params.asset, + )?; + + // i = bits 4..=253 of asset + let i = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "i"), + [RangeConstrained::bitrange_of( + zsa_params.asset.x().value(), + 4..254, + )], + )?; + + // j = j_0 || j_1 || j_2 = (bit 254 of x(asset)) || (ỹ bit of asset) || 8 zero bits + let (j, j_0, j_1) = + DecomposeJ::decompose(chip.clone(), &mut layouter, &zsa_params.asset)?; + + // Check decomposition of `y(asset)`. + let j_1 = y_canonicity( + &lookup_config, + ¬e_commit_chip.config.y_canon, + layouter.namespace(|| "y(asset) decomposition"), + zsa_params.asset.y(), + j_1, + )?; + + ( + h_zec, + h_0, + h_1, + Some(ZsaFinalDecomposition { + h_zsa, + h_2_zsa, + i, + j, + j_0, + j_1, + }), + ) + } + }; // Check decomposition of `y(g_d)`. let b_2 = y_canonicity( @@ -1636,6 +2047,7 @@ pub(in crate::circuit) mod gadgets { g_d.y(), b_2, )?; + // Check decomposition of `y(pk_d)`. let d_1 = y_canonicity( &lookup_config, @@ -1645,45 +2057,172 @@ pub(in crate::circuit) mod gadgets { d_1, )?; - // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) - // - // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition - // constraints allows ⊥ to occur, and then during synthesis it detects these edge - // cases and raises an error (aborting proof creation). - // - // https://p.z.cash/ZKS:action-cm-old-integrity?partial - // https://p.z.cash/ZKS:action-cmx-new-integrity?partial - let (cm, zs) = { - let message = Message::from_pieces( - chip.clone(), - vec![ - a.clone(), - b.clone(), - c.clone(), - d.clone(), - e.clone(), - f.clone(), - g.clone(), - h.clone(), - ], - ); - let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); - domain.commit( - layouter.namespace(|| "Process NoteCommit inputs"), - message, - rcm, - )? + let (cm, zs_common, zs_zsa_suffix) = match (&zsa_params, &zsa_decomposition) { + (None, None) => { + // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) + // + // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition + // constraints allows ⊥ to occur, and then during synthesis it detects these edge + // cases and raises an error (aborting proof creation). + // + // https://p.z.cash/ZKS:action-cm-old-integrity?partial + // https://p.z.cash/ZKS:action-cmx-new-integrity?partial + let message = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + h_zec.clone(), + ], + ); + let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); + let (cm, zs) = domain.commit( + layouter.namespace(|| "Process NoteCommit inputs"), + message, + rcm, + )?; + (cm, zs, vec![]) + } + (Some(zsa_params), Some(zsa_decomposition)) => { + // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi || asset) + // + // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition + // constraints allows ⊥ to occur, and then during synthesis it detects these edge + // cases and raises an error (aborting proof creation). + // + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] for more details. + // [zip226]: https://zips.z.cash/zip-0226#note-structure-commitment. + let message_common_prefix = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + ], + ); + + let message_suffix_zec = Message::from_pieces(chip.clone(), vec![h_zec.clone()]); + + let message_suffix_zsa = Message::from_pieces( + chip.clone(), + vec![ + zsa_decomposition.h_zsa.clone(), + zsa_decomposition.i.clone(), + zsa_decomposition.j.clone(), + ], + ); + + // We will evaluate + // - `hash_point_zec = hash(Q_ZEC, message_common_prefix || message_suffix_zec)`, and + // - `hash_point_zsa = hash(Q_ZSA, message_common_prefix || message_suffix_zsa)`. + // by sharing a portion of the hash evaluation process between `hash_point_zec` and + // `hash_point_zsa`: + // 1. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} + // 2. common_hash = hash(Q, message_common_prefix) // this part is shared + // 3. hash_point_zec = hash(common_hash, message_suffix_zec) + // 4. hash_point_zsa = hash(common_hash, message_suffix_zsa) + // 5. hash_point = if (is_native_asset == 0) {hash_point_zsa} else {hash_point_zec} + let zec_domain = CommitDomain::new( + chip.clone(), + ecc_chip.clone(), + &OrchardCommitDomains::NoteCommit, + ); + let zsa_domain = + CommitDomain::new(chip, ecc_chip.clone(), &OrchardCommitDomains::NoteZsaCommit); + + // Perform a MUX to select the desired initial Q point + // q_init = q_init_zec if is_native_asset is true + // q_init = q_init_zsa if is_native_asset is false + let q_init = { + let q_init_zec = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zec"), + Value::known(zec_domain.q_init()), + )?; + + let q_init_zsa = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zsa"), + Value::known(zsa_domain.q_init()), + )?; + + zsa_params.cond_swap_chip.mux_on_non_identity_points( + layouter.namespace(|| "mux on hash point"), + &zsa_params.is_native_asset, + q_init_zsa.inner(), + q_init_zec.inner(), + )? + }; + + // common_hash = hash(q_init, message_common_prefix) + // + // To evaluate the different hash, we could use either zec_domain or zsa_domain + // because we use a private initial point. + let (common_hash, zs_common) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash common prefix note"), + &q_init, + message_common_prefix, + )?; + + // hash_point_zec = hash(common_hash, message_suffix_zec) = hash(q_init, message_zec) + let (hash_point_zec, _zs_zec) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZEC note"), + common_hash.inner(), + message_suffix_zec, + )?; + + // hash_point_zsa = hash(common_hash, message_suffix_zsa) = hash(q_init, message_zsa) + let (hash_point_zsa, zs_zsa) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZSA note"), + common_hash.inner(), + message_suffix_zsa, + )?; + + // Perform a MUX to select the desired hash point + // hash_point = hash_zec if is_native_asset is true + // hash_point = hash_zsa if is_native_asset is false + let hash_point = Point::from_inner( + ecc_chip, + zsa_params.cond_swap_chip.mux_on_points( + layouter.namespace(|| "mux on hash point"), + &zsa_params.is_native_asset, + &(hash_point_zsa.inner().clone().into()), + &(hash_point_zec.inner().clone().into()), + )?, + ); + + // To evaluate the blinding factor, we could use either zec_domain or zsa_domain + // because they have both the same `R` constant. + let blinding_factor = + zec_domain.blinding_factor(layouter.namespace(|| "[r] R"), rcm)?; + let commitment = + hash_point.add(layouter.namespace(|| "M + [r] R"), &blinding_factor)?; + + (commitment, zs_common, zs_zsa) + } + _ => { + panic!("Either both zsa_params and zsa_decomposition must be provided, or neither.") + } }; - // `CommitDomain::commit` returns the running sum for each `MessagePiece`. Grab + // `CommitDomain::hash` returns the running sum for each `MessagePiece`. Grab // the outputs that we will need for canonicity checks. - let z13_a = zs[0][13].clone(); - let z13_c = zs[2][13].clone(); - let z1_d = zs[3][1].clone(); - let z13_f = zs[5][13].clone(); - let z1_g = zs[6][1].clone(); + let z13_a = zs_common[0][13].clone(); + let z13_c = zs_common[2][13].clone(); + let z1_d = zs_common[3][1].clone(); + let z13_f = zs_common[5][13].clone(); + let z1_g = zs_common[6][1].clone(); let g_2 = z1_g.clone(); - let z13_g = zs[6][13].clone(); + let z13_g = zs_common[6][13].clone(); // Witness and constrain the bounds we need to ensure canonicity. let (a_prime, z13_a_prime) = canon_bitshift_130( @@ -1692,7 +2231,7 @@ pub(in crate::circuit) mod gadgets { a.inner().cell_value(), )?; - let (b3_c_prime, z14_b3_c_prime) = pkd_x_canonicity( + let (b3_c_prime, z14_b3_c_prime) = pkd_asset_x_canonicity( &lookup_config, layouter.namespace(|| "x(pk_d) canonicity"), b_3.clone(), @@ -1714,7 +2253,7 @@ pub(in crate::circuit) mod gadgets { )?; // Finally, assign values to all of the NoteCommit regions. - let cfg = note_commit_chip.config; + let cfg = note_commit_chip.config.clone(); let b_1 = cfg .b @@ -1730,12 +2269,30 @@ pub(in crate::circuit) mod gadgets { .g .assign(&mut layouter, g, g_0, g_1.clone(), z1_g.clone())?; - let h_1 = cfg.h.assign(&mut layouter, h, h_0.clone(), h_1)?; + let h_1 = match ( + &zsa_decomposition, + ¬e_commit_chip.config.specific_config_for_circuit, + ) { + (None, SpecificConfigForCircuit::Vanilla(specific_config)) => specific_config + .h_vanilla + .assign(&mut layouter, h_zec, h_0.clone(), h_1)?, + (Some(zsa_decomposition), SpecificConfigForCircuit::Zsa(specific_config)) => { + specific_config.h_zsa.assign( + &mut layouter, + h_zec, + zsa_decomposition.h_zsa.clone(), + h_0.clone(), + h_1, + zsa_decomposition.h_2_zsa.clone(), + )? + } + _ => panic!("zsa_decomposition is required with a ZSA configuration but must be omitted with a Vanilla configuration."), + }; cfg.g_d .assign(&mut layouter, g_d, a, b_0, b_1, a_prime, z13_a, z13_a_prime)?; - cfg.pk_d.assign( + cfg.pk_d_asset.assign( &mut layouter, pk_d, b_3, @@ -1771,6 +2328,42 @@ pub(in crate::circuit) mod gadgets { z13_g1_g2_prime, )?; + if let ( + Some(zsa_decomposition), + Some(zsa_params), + SpecificConfigForCircuit::Zsa(specific_config), + ) = ( + zsa_decomposition, + &zsa_params, + ¬e_commit_chip.config.specific_config_for_circuit, + ) { + let j_0 = specific_config.j.assign( + &mut layouter, + zsa_decomposition.j, + zsa_decomposition.j_0, + zsa_decomposition.j_1, + )?; + + let (h2_i_prime, z14_h2_i_prime) = pkd_asset_x_canonicity( + &lookup_config, + layouter.namespace(|| "x(asset) canonicity"), + zsa_decomposition.h_2_zsa.clone(), + zsa_decomposition.i.inner().cell_value(), + )?; + + let z13_i = zs_zsa_suffix[1][13].clone(); + cfg.pk_d_asset.assign( + &mut layouter, + &zsa_params.asset, + zsa_decomposition.h_2_zsa, + zsa_decomposition.i, + j_0, + h2_i_prime, + z13_i, + z14_h2_i_prime, + )?; + } + Ok(cm) } @@ -1779,8 +2372,8 @@ pub(in crate::circuit) mod gadgets { /// Specifications: /// - [`g_d` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-g_d?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn canon_bitshift_130( - lookup_config: &LookupRangeCheckConfig, + fn canon_bitshift_130( + lookup_config: &Lookup, mut layouter: impl Layouter, a: AssignedCell, ) -> Result { @@ -1810,15 +2403,16 @@ pub(in crate::circuit) mod gadgets { Ok((a_prime, zs[13].clone())) } - /// Check canonicity of `x(pk_d)` encoding. + /// Check canonicity of `x(pk_d)` and `x(asset)` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). - fn pkd_x_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn pkd_asset_x_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, b_3: RangeConstrained>, c: AssignedCell, ) -> Result { + // Example for `x(pk_d)`: // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` // - d_0 = 1 => b_3 + 2^4 c < t_P // - 0 ≤ b_3 + 2^4 c < 2^134 @@ -1828,6 +2422,7 @@ pub(in crate::circuit) mod gadgets { // - z_13 of SinsemillaHash(c) == 0 constrains bits 4..=253 of pkd_x // to 130 bits. z13_c is directly checked in the gate. // - 0 ≤ b_3 + 2^4 c + 2^140 - t_P < 2^140 (14 ten-bit lookups) + // For `x(asset)`, we have to replace `pk_d`, `b_3`, `c`, `d_0` by `asset`, `h_2_zsa`, `i`, `j_0` // Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P, // and output the running sum at the end of it. @@ -1854,8 +2449,8 @@ pub(in crate::circuit) mod gadgets { /// Check canonicity of `rho` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-rho?partial). - fn rho_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn rho_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, e_1: RangeConstrained>, f: AssignedCell, @@ -1895,8 +2490,8 @@ pub(in crate::circuit) mod gadgets { /// Check canonicity of `psi` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-psi?partial). - fn psi_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn psi_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, g_1: RangeConstrained>, g_2: AssignedCell, @@ -1937,8 +2532,8 @@ pub(in crate::circuit) mod gadgets { /// Specifications: /// - [`y` decomposition](https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn y_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn y_canonicity( + lookup_config: &Lookup, y_canon: &YCanonicity, mut layouter: impl Layouter, y: AssignedCell, @@ -2015,16 +2610,15 @@ pub(in crate::circuit) mod gadgets { mod tests { use core::iter; - use super::NoteCommitConfig; use crate::{ - circuit::{ - gadget::assign_free_advice, - note_commit::{gadgets, NoteCommitChip}, - }, + circuit::gadget::{assign_free_advice, assign_is_native_asset}, + circuit::note_commit::gadgets, + circuit::note_commit::{NoteCommitChip, NoteCommitConfig}, constants::{ fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, }, + note::{commitment::NoteCommitTrapdoor, AssetBase, NoteCommitment}, value::NoteValue, }; use halo2_gadgets::{ @@ -2032,24 +2626,30 @@ mod tests { chip::{EccChip, EccConfig}, NonIdentityPoint, ScalarFixed, }, - sinsemilla::chip::SinsemillaChip, - sinsemilla::primitives::CommitDomain, - utilities::lookup_range_check::LookupRangeCheckConfig, + sinsemilla::{chip::SinsemillaChip, primitives::CommitDomain}, + utilities::{ + cond_swap::{CondSwapChip, CondSwapConfig}, + lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfig, PallasLookupRangeCheck4_5BConfig, + PallasLookupRangeCheckConfig, + }, + }, }; use ff::{Field, PrimeField, PrimeFieldBits}; - use group::Curve; + use group::{Curve, Group, GroupEncoding}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use pasta_curves::{arithmetic::CurveAffine, pallas}; + use pasta_curves::{arithmetic::CurveAffine, pallas, EpAffine}; + use crate::circuit::note_commit::ZsaNoteCommitParams; use rand::{rngs::OsRng, RngCore}; #[test] - fn note_commit() { + fn note_commit_vanilla() { #[derive(Default)] struct MyCircuit { gd_x: Value, @@ -2061,7 +2661,10 @@ mod tests { } impl Circuit for MyCircuit { - type Config = (NoteCommitConfig, EccConfig); + type Config = ( + NoteCommitConfig, + EccConfig, + ); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -2119,9 +2722,10 @@ mod tests { lagrange_coeffs[0], lookup, range_check, + false, ); let note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config); + NoteCommitChip::configure(meta, advices, sinsemilla_config, false); let ecc_config = EccChip::::configure( meta, @@ -2142,10 +2746,10 @@ mod tests { // Load the Sinsemilla generator lookup table used by the whole circuit. SinsemillaChip::< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; // Construct a Sinsemilla chip let sinsemilla_chip = @@ -2239,6 +2843,7 @@ mod tests { rho, psi, rcm_gadget, + None, )?; let expected_cm = { let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); @@ -2357,4 +2962,371 @@ mod tests { assert_eq!(prover.verify(), Ok(())); } } + + #[test] + fn note_commit_zsa() { + #[derive(Default)] + struct MyCircuit { + g_d: Value, + pk_d: Value, + rho: Value, + psi: Value, + asset: Value, + } + + impl Circuit for MyCircuit { + type Config = ( + NoteCommitConfig, + EccConfig, + CondSwapConfig, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants. + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + let range_check = PallasLookupRangeCheck4_5BConfig::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); + let sinsemilla_config = SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck4_5BConfig, + >::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + true, + ); + let note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config, true); + + let ecc_config = + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + let cond_swap_config = + CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); + + (note_commit_config, ecc_config, cond_swap_config) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (note_commit_config, ecc_config, cond_swap_config) = config; + + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck4_5BConfig, + >::load( + note_commit_config.sinsemilla_config.clone(), &mut layouter + )?; + + // Construct a Sinsemilla chip + let sinsemilla_chip = + SinsemillaChip::construct(note_commit_config.sinsemilla_config.clone()); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(ecc_config); + + // Construct a NoteCommit chip + let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); + + // Construct a CondSwap chip + let cond_swap_chip = CondSwapChip::construct(cond_swap_config); + + // Witness g_d + let g_d = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d"), + self.g_d, + )?; + + // Witness pk_d + let pk_d = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d"), + self.pk_d, + )?; + + // Witness a random non-negative u64 note value + // A note value cannot be negative. + let value = { + let mut rng = OsRng; + NoteValue::from_raw(rng.next_u64()) + }; + let value_var = { + assign_free_advice( + layouter.namespace(|| "witness value"), + note_commit_config.advices[0], + Value::known(value), + )? + }; + + // Witness rho + let rho = assign_free_advice( + layouter.namespace(|| "witness rho"), + note_commit_config.advices[0], + self.rho, + )?; + + // Witness psi + let psi = assign_free_advice( + layouter.namespace(|| "witness psi"), + note_commit_config.advices[0], + self.psi, + )?; + + let rcm = pallas::Scalar::random(OsRng); + let rcm_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm"), + Value::known(rcm), + )?; + + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + let is_native_asset = assign_is_native_asset( + layouter.namespace(|| "witness is_native_asset"), + note_commit_config.advices[0], + self.asset, + )?; + let cm = gadgets::note_commit( + layouter.namespace(|| "Hash NoteCommit pieces"), + sinsemilla_chip, + ecc_chip.clone(), + note_commit_chip, + g_d.inner(), + pk_d.inner(), + value_var, + rho, + psi, + rcm_gadget, + Some(ZsaNoteCommitParams { + cond_swap_chip, + asset: asset.inner().clone(), + is_native_asset, + }), + )?; + let expected_cm = { + // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi + let point = self + .g_d + .zip(self.pk_d) + .zip(self.rho.zip(self.psi)) + .zip(self.asset) + .map(|(((g_d, pk_d), (rho, psi)), asset)| { + NoteCommitment::derive( + g_d.to_bytes(), + pk_d.to_bytes(), + value, + asset, + rho, + psi, + NoteCommitTrapdoor(rcm), + ) + .unwrap() + .inner() + .to_affine() + }); + NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? + }; + cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm) + } + } + + fn affine_point_from_coordinates(x_coord: pallas::Base, y_lsb: pallas::Base) -> EpAffine { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x_coord.square() * x_coord + pallas::Affine::b()) + .sqrt() + .unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x_coord, y).unwrap() + } + + let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); + let mut rng = OsRng; + let random_asset = AssetBase::random(); + + // Test different values of `ak`, `nk` + let mut circuits = vec![]; + for asset in [random_asset, AssetBase::native()] { + // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) + // `rho` = 0, `psi` = 0 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + rho: Value::known(pallas::Base::zero()), + psi: Value::known(pallas::Base::zero()), + asset: Value::known(asset), + }); + // `rho` = T_Q - 1, `psi` = T_Q - 1 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + rho: Value::known(pallas::Base::from_u128(T_Q - 1)), + psi: Value::known(pallas::Base::from_u128(T_Q - 1)), + asset: Value::known(asset), + }); + // `rho` = T_Q, `psi` = T_Q + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + rho: Value::known(pallas::Base::from_u128(T_Q)), + psi: Value::known(pallas::Base::from_u128(T_Q)), + asset: Value::known(asset), + }); + // `rho` = 2^127 - 1, `psi` = 2^127 - 1 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + asset: Value::known(asset), + }); + // `rho` = 2^127, `psi` = 2^127 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + rho: Value::known(pallas::Base::from_u128(1 << 127)), + psi: Value::known(pallas::Base::from_u128(1 << 127)), + asset: Value::known(asset), + }); + // `rho` = 2^254 - 1, `psi` = 2^254 - 1 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + rho: Value::known(two_pow_254 - pallas::Base::one()), + psi: Value::known(two_pow_254 - pallas::Base::one()), + asset: Value::known(asset), + }); + // `rho` = 2^254, `psi` = 2^254 + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + rho: Value::known(two_pow_254), + psi: Value::known(two_pow_254), + asset: Value::known(asset), + }); + // Random values + circuits.push(MyCircuit { + g_d: Value::known(pallas::Point::random(rng).to_affine()), + pk_d: Value::known(pallas::Point::random(rng).to_affine()), + rho: Value::known(pallas::Base::random(&mut rng)), + psi: Value::known(pallas::Base::random(&mut rng)), + asset: Value::known(asset), + }); + } + + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } } diff --git a/src/circuit/orchard_sinsemilla_chip.rs b/src/circuit/orchard_sinsemilla_chip.rs new file mode 100644 index 000000000..c58399d8b --- /dev/null +++ b/src/circuit/orchard_sinsemilla_chip.rs @@ -0,0 +1,88 @@ +//! Defines the `OrchardSinsemillaChip` trait to abstract over `SinsemillaChip` and `SinsemillaChip` types. +//! Used to generalize the `commit_ivk` function. + +use pasta_curves::pallas; + +use halo2_proofs::circuit::Chip; + +use halo2_gadgets::{ + sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + primitives as sinsemilla, SinsemillaInstructions, + }, + utilities::lookup_range_check::PallasLookupRangeCheck, +}; + +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; + +type BaseSinsemillaChip = + SinsemillaChip; + +pub(super) trait OrchardSinsemillaChip: + SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + CellValue = >::CellValue, + Message = >::Message, + MessagePiece = >::MessagePiece, + RunningSum = >::RunningSum, + X = >::X, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + HashDomains = >::HashDomains, + CommitDomains = >::CommitDomains, + > + Chip< + pallas::Base, + Config = SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + Lookup, + >, + > + Clone + + std::fmt::Debug + + Eq +{ +} + +impl OrchardSinsemillaChip + for SinsemillaChip +{ +} diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs new file mode 100644 index 000000000..ae8b4ea31 --- /dev/null +++ b/src/circuit/value_commit_orchard.rs @@ -0,0 +1,390 @@ +//! Value commitment logic for the Orchard circuit. + +use pasta_curves::pallas; + +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; + +use halo2_gadgets::utilities::lookup_range_check::PallasLookupRangeCheck; +use halo2_gadgets::{ + ecc::{chip::EccChip, NonIdentityPoint}, + sinsemilla::chip::SinsemillaChip, +}; + +pub struct ZsaValueCommitParams { + pub sinsemilla_chip: + SinsemillaChip, + pub asset: NonIdentityPoint>, +} + +pub(in crate::circuit) mod gadgets { + use super::*; + + use crate::constants::{OrchardFixedBasesFull, ValueCommitV}; + + use halo2_gadgets::{ + ecc::{FixedPoint, FixedPointShort, Point, ScalarFixed, ScalarFixedShort, ScalarVar}, + sinsemilla, + utilities::lookup_range_check::PallasLookupRangeCheck, + }; + + use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter}, + plonk, + }; + + /// `ValueCommit^Orchard` from [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226]. + /// + /// [zip226]: https://zips.z.cash/zip-0226#value-commitment-correctness + pub(in crate::circuit) fn value_commit_orchard( + mut layouter: impl Layouter, + ecc_chip: EccChip, + v_net_magnitude_sign: ( + AssignedCell, + AssignedCell, + ), + rcv: ScalarFixed>, + zsa_params: Option>, + ) -> Result>, plonk::Error> { + // Evaluate commitment = [v_net_magnitude_sign] asset + let commitment = match zsa_params { + None => { + let v_net = ScalarFixedShort::new( + ecc_chip.clone(), + layouter.namespace(|| "v_net"), + v_net_magnitude_sign, + )?; + + // commitment = [v_net] ValueCommitV + let (commitment, _) = { + let value_commit_v = ValueCommitV; + let value_commit_v = + FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); + value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v_net)? + }; + commitment + } + Some(params) => { + // Check that magnitude is 64 bits + // Note: if zsa_params is not provided, this check will be performed inside the + // fixed-base short scalar multiplication. + { + let lookup_config = params.sinsemilla_chip.config().lookup_config(); + let (magnitude_words, magnitude_extra_bits) = (6, 4); + assert_eq!( + magnitude_words * sinsemilla::primitives::K + magnitude_extra_bits, + 64 + ); + let magnitude_zs = lookup_config.copy_check( + layouter.namespace(|| "magnitude lowest 60 bits"), + v_net_magnitude_sign.0.clone(), + magnitude_words, // 6 windows of 10 bits. + false, // Do not constrain the result here. + )?; + assert_eq!(magnitude_zs.len(), magnitude_words + 1); + lookup_config.copy_short_check( + layouter.namespace(|| "magnitude highest 4 bits"), + magnitude_zs[magnitude_words].clone(), + magnitude_extra_bits, // The 7th window must be a 4 bits value. + )?; + } + + // Multiply asset by magnitude, using the long scalar mul. + // TODO: implement a new variable base multiplication which is optimized for 64-bit scalar + // (the long scalar mul is optimized for pallas::Base scalar (~255-bits)) + // + // magnitude_asset = [magnitude] asset + let magnitude_asset = { + let magnitude_scalar = ScalarVar::from_base( + ecc_chip.clone(), + layouter.namespace(|| "magnitude"), + &v_net_magnitude_sign.0, + )?; + let (magnitude_asset, _) = params + .asset + .mul(layouter.namespace(|| "[magnitude] asset"), magnitude_scalar)?; + magnitude_asset + }; + + // commitment = [sign] magnitude_asset = [v_net_magnitude_sign] asset + magnitude_asset.mul_sign( + layouter.namespace(|| "[sign] commitment"), + &v_net_magnitude_sign.1, + )? + } + }; + + // blind = [rcv] ValueCommitR + let (blind, _rcv) = { + let value_commit_r = OrchardFixedBasesFull::ValueCommitR; + let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); + + // [rcv] ValueCommitR + value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? + }; + + // [v] ValueCommitV + [rcv] ValueCommitR + commitment.add(layouter.namespace(|| "cv"), &blind) + } +} + +#[cfg(test)] +mod tests { + use crate::{ + circuit::gadget::assign_free_advice, + circuit::value_commit_orchard::gadgets::value_commit_orchard, + circuit::K, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, + }; + use halo2_gadgets::{ + ecc::{ + chip::{EccChip, EccConfig}, + NonIdentityPoint, ScalarFixed, + }, + sinsemilla::chip::{SinsemillaChip, SinsemillaConfig}, + utilities::lookup_range_check::{ + LookupRangeCheck4_5BConfig, PallasLookupRangeCheck4_5BConfig, + }, + }; + + use group::Curve; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, + }; + use pasta_curves::pallas; + + use crate::circuit::value_commit_orchard::ZsaValueCommitParams; + use rand::{rngs::OsRng, RngCore}; + + #[test] + fn test_value_commit_orchard() { + #[derive(Clone, Debug)] + pub struct MyConfig { + primary: Column, + advices: [Column; 10], + ecc_config: EccConfig, + // Sinsemilla config is only used to initialize the table_idx lookup table in the same + // way as in the Orchard circuit + sinsemilla_config: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck4_5BConfig, + >, + } + #[derive(Default)] + struct MyCircuit { + v_old: Value, + v_new: Value, + rcv: Value, + asset: Value, + split_flag: Value, + } + + impl Circuit for MyCircuit { + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let range_check = LookupRangeCheck4_5BConfig::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); + + let sinsemilla_config = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + true, + ); + + MyConfig { + primary, + advices, + ecc_config: + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ), + sinsemilla_config, + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load the Sinsemilla generator lookup table. + SinsemillaChip::load(config.sinsemilla_config.clone(), &mut layouter)?; + + // Construct an ECC chip + let ecc_chip = EccChip::construct(config.ecc_config); + + let sinsemilla_chip = SinsemillaChip::construct(config.sinsemilla_config.clone()); + + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + // v_net is equal to + // (-v_new) if split_flag = true + // v_old - v_new if split_flag = false + let v_net = self.split_flag.and_then(|split_flag| { + if split_flag { + Value::known(crate::value::NoteValue::zero()) - self.v_new + } else { + self.v_old - self.v_new + } + }); + + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + // Witness rcv + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + self.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + // Witness asset + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + // Evaluate cv_net with value_commit_orchard + let cv_net = value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), + ecc_chip, + v_net_magnitude_sign, + rcv, + Some(ZsaValueCommitParams { + sinsemilla_chip, + asset, + }), + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, 0)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, 1) + } + } + + // Test different circuits + let mut rng = OsRng; + let mut circuits = vec![]; + let mut instances = vec![]; + let native_asset = AssetBase::native(); + let random_asset = AssetBase::random(); + for split_flag in [false, true] { + for asset in [native_asset, random_asset] { + let v_old = NoteValue::from_raw(rng.next_u64()); + let v_new = NoteValue::from_raw(rng.next_u64()); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let v_net = if split_flag { + NoteValue::zero() - v_new + } else { + v_old - v_new + }; + circuits.push(MyCircuit { + v_old: Value::known(v_old), + v_new: Value::known(v_new), + rcv: Value::known(rcv), + asset: Value::known(asset), + split_flag: Value::known(split_flag), + }); + let expected_cv_net = ValueCommitment::derive(v_net, rcv, asset); + instances.push([[expected_cv_net.x(), expected_cv_net.y()]]); + } + } + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + K, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } +} diff --git a/src/constants.rs b/src/constants.rs index 8a9b76f23..a9b631c8c 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,9 +1,11 @@ //! Constants used in the Orchard protocol. pub mod fixed_bases; +pub mod nullifier_l; +pub mod reference_keys; pub mod sinsemilla; pub mod util; -pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV, H}; +pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV}; pub use sinsemilla::{OrchardCommitDomains, OrchardHashDomains}; /// $\mathsf{MerkleDepth^{Orchard}}$ diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index af11e335f..12ab8a47e 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -21,8 +21,11 @@ pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard"; /// SWU hash-to-curve personalization for the value commitment generator pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv"; +/// SWU hash-to-curve personalization for the ZSA asset base generator +pub const ZSA_ASSET_BASE_PERSONALIZATION: &str = "z.cash:OrchardZSA"; + /// SWU hash-to-curve value for the value commitment generator -pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v"; +pub const NATIVE_ASSET_BASE_V_BYTES: [u8; 1] = *b"v"; /// SWU hash-to-curve value for the value commitment generator pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r"; @@ -30,6 +33,9 @@ pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r"; /// SWU hash-to-curve personalization for the note commitment generator pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit"; +/// SWU hash-to-curve personalization for the ZSA note commitment generator +pub const NOTE_ZSA_COMMITMENT_PERSONALIZATION: &str = "z.cash:ZSA-NoteCommit"; + /// SWU hash-to-curve personalization for the IVK commitment generator pub const COMMIT_IVK_PERSONALIZATION: &str = "z.cash:Orchard-CommitIvk"; diff --git a/src/constants/nullifier_l.rs b/src/constants/nullifier_l.rs new file mode 100644 index 000000000..f4c2ac58c --- /dev/null +++ b/src/constants/nullifier_l.rs @@ -0,0 +1,44 @@ +//! $\mathcal{L}^{\mathsf{Orchard}}$ constant. +//! +//! This constant is used to evaluate the nullifier of a split note (ZIP 226). + +use pasta_curves::{arithmetic::CurveAffine, pallas}; + +/// Constant used as $\mathcal{L}^{\mathsf{Orchard}}$ in DeriveNullifier. +pub const NULLIFIER_L: (pallas::Base, pallas::Base) = ( + pallas::Base::from_raw([ + 0x7956_0ba9_2372_5d67, + 0xcb79_efc2_91c1_b0c8, + 0xbbed_d606_d1df_737e, + 0x032e_6e8c_f01d_3ea1, + ]), + pallas::Base::from_raw([ + 0x8838_95de_f68a_1265, + 0xd861_4d8d_ab43_e39e, + 0xf9e6_ebb2_b7b5_6640, + 0x093c_af7e_c368_376e, + ]), +); + +pub fn nullifier_l() -> pallas::Affine { + pallas::Affine::from_xy(NULLIFIER_L.0, NULLIFIER_L.1).unwrap() +} + +#[cfg(test)] +mod tests { + use super::*; + use group::Curve; + use pasta_curves::arithmetic::CurveAffine; + use pasta_curves::arithmetic::CurveExt; + + #[test] + fn nullifier_l() { + let expected_nullifier_l = pallas::Point::hash_to_curve("z.cash:Orchard")(b"L") + .to_affine() + .coordinates() + .unwrap(); + + assert_eq!(*expected_nullifier_l.x(), NULLIFIER_L.0); + assert_eq!(*expected_nullifier_l.y(), NULLIFIER_L.1); + } +} diff --git a/src/constants/reference_keys.rs b/src/constants/reference_keys.rs new file mode 100644 index 000000000..535528000 --- /dev/null +++ b/src/constants/reference_keys.rs @@ -0,0 +1,54 @@ +//! Orchard reference keys, including the spending key and recipient address, used for reference notes. +//! +//! The reference SpendingKey is a placeholder key with all bytes set to zero. +//! Using this SpendingKey, we derive the FullViewingKey, and the recipient address. +//! To avoid repeating the derivation process whenever the recipient address is required, we store +//! its raw encoding. + +use crate::{ + address::Address, + keys::{FullViewingKey, SpendingKey}, +}; + +/// Raw bytes representation of the reference recipient address. +pub const RAW_REFERENCE_RECIPIENT: [u8; 43] = [ + 204, 54, 96, 25, 89, 33, 59, 107, 12, 219, 150, 167, 92, 23, 195, 166, 104, 169, 127, 13, 106, + 140, 92, 225, 100, 165, 24, 234, 155, 169, 165, 14, 167, 81, 145, 253, 134, 27, 15, 241, 14, + 98, 176, +]; + +/// Reference keys (spending key and recipient address) are used for reference notes. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct ReferenceKeys; + +impl ReferenceKeys { + /// Returns the spending key for reference notes. + pub fn sk() -> SpendingKey { + SpendingKey::from_bytes([0; 32]).unwrap() + } + + /// Returns the recipient address for reference notes. + pub fn recipient() -> Address { + Address::from_raw_address_bytes(&RAW_REFERENCE_RECIPIENT).unwrap() + } + + /// Returns the full viewing key for reference notes. + pub fn fvk() -> FullViewingKey { + FullViewingKey::from(&Self::sk()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::keys::{FullViewingKey, Scope}; + + #[test] + fn recipient() { + let sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + + assert_eq!(recipient, ReferenceKeys::recipient()); + } +} diff --git a/src/constants/sinsemilla.rs b/src/constants/sinsemilla.rs index f6c6ffba6..1e43306f4 100644 --- a/src/constants/sinsemilla.rs +++ b/src/constants/sinsemilla.rs @@ -37,6 +37,18 @@ pub const Q_NOTE_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = ( ], ); +/// Generator used in SinsemillaHashToPoint for ZSA note commitment +pub const Q_NOTE_ZSA_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = ( + [ + 207, 235, 191, 45, 66, 225, 8, 126, 199, 188, 39, 26, 115, 106, 18, 2, 191, 173, 75, 9, 65, + 225, 175, 193, 224, 202, 228, 177, 3, 75, 228, 1, + ], + [ + 220, 251, 80, 86, 182, 182, 99, 67, 254, 97, 241, 22, 79, 111, 161, 176, 79, 97, 208, 98, + 116, 57, 110, 196, 25, 73, 239, 31, 196, 97, 19, 30, + ], +); + /// Generator used in SinsemillaHashToPoint for IVK commitment pub const Q_COMMIT_IVK_M_GENERATOR: ([u8; 32], [u8; 32]) = ( [ @@ -78,6 +90,7 @@ pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] { #[derive(Clone, Debug, Eq, PartialEq)] pub enum OrchardHashDomains { NoteCommit, + NoteZsaCommit, CommitIvk, MerkleCrh, } @@ -96,6 +109,11 @@ impl HashDomains for OrchardHashDomains { pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(), ) .unwrap(), + OrchardHashDomains::NoteZsaCommit => pallas::Affine::from_xy( + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.0).unwrap(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.1).unwrap(), + ) + .unwrap(), OrchardHashDomains::MerkleCrh => pallas::Affine::from_xy( pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap(), pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap(), @@ -108,6 +126,7 @@ impl HashDomains for OrchardHashDomains { #[derive(Clone, Debug, Eq, PartialEq)] pub enum OrchardCommitDomains { NoteCommit, + NoteZsaCommit, CommitIvk, } @@ -115,6 +134,8 @@ impl CommitDomains for Or fn r(&self) -> OrchardFixedBasesFull { match self { Self::NoteCommit => OrchardFixedBasesFull::NoteCommitR, + // For ZSA note commitment, we use the same `R` than for ZEC note commitment. + Self::NoteZsaCommit => OrchardFixedBasesFull::NoteCommitR, Self::CommitIvk => OrchardFixedBasesFull::CommitIvkR, } } @@ -122,6 +143,7 @@ impl CommitDomains for Or fn hash_domain(&self) -> OrchardHashDomains { match self { Self::NoteCommit => OrchardHashDomains::NoteCommit, + Self::NoteZsaCommit => OrchardHashDomains::NoteZsaCommit, Self::CommitIvk => OrchardHashDomains::CommitIvk, } } @@ -131,7 +153,10 @@ impl CommitDomains for Or mod tests { use super::*; use crate::constants::{ - fixed_bases::{COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION}, + fixed_bases::{ + COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION, + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + }, sinsemilla::MERKLE_CRH_PERSONALIZATION, }; use group::{ff::PrimeField, Curve}; @@ -192,6 +217,22 @@ mod tests { ); } + #[test] + fn q_note_zsa_commitment_m() { + let domain = CommitDomain::new(NOTE_ZSA_COMMITMENT_PERSONALIZATION); + let point = domain.Q(); + let coords = point.to_affine().coordinates().unwrap(); + + assert_eq!( + *coords.x(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.0).unwrap() + ); + assert_eq!( + *coords.y(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.1).unwrap() + ); + } + #[test] fn q_commit_ivk_m() { let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); diff --git a/src/domain.rs b/src/domain.rs new file mode 100644 index 000000000..1632480c7 --- /dev/null +++ b/src/domain.rs @@ -0,0 +1,17 @@ +//! In-band secret distribution for Orchard bundles. +//! +//! This module handles the encryption and decryption of notes within the Orchard protocol, +//! It includes functionality for handling both the standard "Vanilla" variantion and the ZSA +//! variantion, with different implementations for each. The different implementations are +//! organized into separate submodules. + +mod compact_action; +mod orchard_domain; +mod orchard_domain_vanilla; +mod orchard_domain_zsa; +mod zcash_note_encryption_domain; + +pub use { + compact_action::CompactAction, + orchard_domain::{OrchardDomain, OrchardDomainCommon}, +}; diff --git a/src/domain/compact_action.rs b/src/domain/compact_action.rs new file mode 100644 index 000000000..dcf2854a0 --- /dev/null +++ b/src/domain/compact_action.rs @@ -0,0 +1,171 @@ +//! Defines actions for Orchard shielded outputs and compact action for light clients. + +use std::fmt; + +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, EphemeralKeyBytes, ShieldedOutput}; + +use crate::{ + action::Action, + note::{ExtractedNoteCommitment, Nullifier, Rho}, +}; + +use super::orchard_domain::{OrchardDomain, OrchardDomainCommon}; + +impl ShieldedOutput> for Action { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.encrypted_note().epk_bytes) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx().to_bytes() + } + + fn enc_ciphertext(&self) -> Option<&D::NoteCiphertextBytes> { + Some(&self.encrypted_note().enc_ciphertext) + } + + fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { + D::CompactNoteCiphertextBytes::from_slice( + &self.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE], + ) + .unwrap() + } +} + +/// A compact Action for light clients. +#[derive(Clone)] +pub struct CompactAction { + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: D::CompactNoteCiphertextBytes, +} + +impl fmt::Debug for CompactAction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "CompactAction") + } +} + +impl From<&Action> for CompactAction +where + Action: ShieldedOutput>, +{ + fn from(action: &Action) -> Self { + CompactAction { + nullifier: *action.nullifier(), + cmx: *action.cmx(), + ephemeral_key: action.ephemeral_key(), + enc_ciphertext: action.enc_ciphertext_compact(), + } + } +} + +impl ShieldedOutput> for CompactAction { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.ephemeral_key.0) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx.to_bytes() + } + + fn enc_ciphertext(&self) -> Option<&D::NoteCiphertextBytes> { + None + } + + fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { + D::CompactNoteCiphertextBytes::from_slice(self.enc_ciphertext.as_ref()).unwrap() + } +} + +impl CompactAction { + /// Create a CompactAction from its constituent parts + pub fn from_parts( + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: D::CompactNoteCiphertextBytes, + ) -> Self { + Self { + nullifier, + cmx, + ephemeral_key, + enc_ciphertext, + } + } + + /// Returns the nullifier of the note being spent. + pub fn nullifier(&self) -> Nullifier { + self.nullifier + } + + /// Returns the commitment to the new note being created. + pub fn cmx(&self) -> ExtractedNoteCommitment { + self.cmx + } + + /// Obtains the [`Rho`] value that was used to construct the new note being created. + pub fn rho(&self) -> Rho { + Rho::from_nf_old(self.nullifier) + } +} + +/// Utilities for constructing test data. +#[cfg(feature = "test-dependencies")] +pub mod testing { + use rand::RngCore; + + use zcash_note_encryption_zsa::{note_bytes::NoteBytes, Domain, NoteEncryption}; + + use crate::{ + address::Address, + domain::zcash_note_encryption_domain::MEMO_SIZE, + keys::OutgoingViewingKey, + note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho}, + value::NoteValue, + }; + + use super::{CompactAction, OrchardDomain, OrchardDomainCommon}; + + /// Creates a fake `CompactAction` paying the given recipient the specified value. + /// + /// Returns the `CompactAction` and the new note. + pub fn fake_compact_action( + rng: &mut R, + nf_old: Nullifier, + recipient: Address, + value: NoteValue, + ovk: Option, + ) -> (CompactAction, Note) { + let rho = Rho::from_nf_old(nf_old); + let rseed = { + loop { + let mut bytes = [0; 32]; + rng.fill_bytes(&mut bytes); + let rseed = RandomSeed::from_bytes(bytes, &rho); + if rseed.is_some().into() { + break rseed.unwrap(); + } + } + }; + let note = Note::from_parts(recipient, value, AssetBase::native(), rho, rseed).unwrap(); + let encryptor = NoteEncryption::>::new(ovk, note, [0u8; MEMO_SIZE]); + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let ephemeral_key = OrchardDomain::::epk_bytes(encryptor.epk()); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + ( + CompactAction { + nullifier: nf_old, + cmx, + ephemeral_key, + enc_ciphertext: D::CompactNoteCiphertextBytes::from_slice( + &enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE], + ) + .unwrap(), + }, + note, + ) + } +} diff --git a/src/domain/orchard_domain.rs b/src/domain/orchard_domain.rs new file mode 100644 index 000000000..5249a918d --- /dev/null +++ b/src/domain/orchard_domain.rs @@ -0,0 +1,158 @@ +//! The OrchardDomain trait represents the difference between the `OrchardVanilla` and the +//! `OrchardZSA` commitment, encryption and decryption procedures. + +use core::fmt; + +use blake2b_simd::{Hash as Blake2bHash, State}; +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE}; + +use crate::{ + action::Action, + bundle::{ + commitments::{ + hasher, ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION, + ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION, + ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION, + }, + Authorization, Authorized, + }, + domain::{ + compact_action::CompactAction, + zcash_note_encryption_domain::{Memo, MEMO_SIZE}, + }, + note::{AssetBase, Rho}, + Bundle, Note, +}; + +/// Represents the Orchard protocol domain specifics required for note encryption and decryption. +pub trait OrchardDomainCommon: fmt::Debug + Clone { + /// The size of a compact note, specific to the Orchard protocol. + const COMPACT_NOTE_SIZE: usize; + + /// The size of a note plaintext, including memo and other metadata. + const NOTE_PLAINTEXT_SIZE: usize = Self::COMPACT_NOTE_SIZE + MEMO_SIZE; + + /// The size of an encrypted note ciphertext, accounting for additional AEAD tag space. + const ENC_CIPHERTEXT_SIZE: usize = Self::NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE; + + /// The raw bytes of a note plaintext. + type NotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted note plaintext. + type NoteCiphertextBytes: NoteBytes; + /// The raw bytes of a compact note. + type CompactNotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted compact note. + type CompactNoteCiphertextBytes: NoteBytes; + + /// Builds NotePlaintextBytes from Note and Memo. + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes; + + /// Extracts the asset from the note plaintext. + fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option; + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// for OrchardVanilla and as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// for OrchardZSA + /// + /// [zip244]: https://zips.z.cash/zip-0244 + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash; + + /// Incorporates the hash of: + /// orchard_actions_compact_digest, + /// orchard_actions_memos_digest, + /// orchard_actions_noncompact_digest + /// into the hasher. + /// + /// More precisely, write disjoint parts of each Orchard shielded action as 3 separate hashes: + /// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized + /// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION + /// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized + /// with ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION + /// * \[(cv, rk, enc_ciphertext\[564..\], out_ciphertext)*\] personalized + /// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION + /// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn update_hash_with_actions>( + main_hasher: &mut State, + bundle: &Bundle, + ) { + let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION); + let mut mh = hasher(ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION); + let mut nh = hasher(ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION); + + for action in bundle.actions().iter() { + ch.update(&action.nullifier().to_bytes()); + ch.update(&action.cmx().to_bytes()); + ch.update(&action.encrypted_note().epk_bytes); + ch.update(&action.encrypted_note().enc_ciphertext.as_ref()[..Self::COMPACT_NOTE_SIZE]); + + mh.update( + &action.encrypted_note().enc_ciphertext.as_ref() + [Self::COMPACT_NOTE_SIZE..Self::COMPACT_NOTE_SIZE + MEMO_SIZE], + ); + + nh.update(&action.cv_net().to_bytes()); + nh.update(&<[u8; 32]>::from(action.rk())); + nh.update( + &action.encrypted_note().enc_ciphertext.as_ref() + [Self::COMPACT_NOTE_SIZE + MEMO_SIZE..], + ); + nh.update(&action.encrypted_note().out_ciphertext); + } + + main_hasher.update(ch.finalize().as_bytes()); + main_hasher.update(mh.finalize().as_bytes()); + main_hasher.update(nh.finalize().as_bytes()); + } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// for OrchardVanilla and as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// for OrchardZSA + /// + /// [zip244]: https://zips.z.cash/zip-0244 + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash; +} + +/// Orchard-specific note encryption logic. +#[derive(Debug, Clone)] +pub struct OrchardDomain { + /// A parameter needed to generate the nullifier. + pub rho: Rho, + phantom: std::marker::PhantomData, +} + +impl OrchardDomain { + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_action(act: &Action) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_compact_action(act: &CompactAction) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain from a rho. + #[cfg(test)] + pub fn for_rho(rho: Rho) -> Self { + Self { + rho, + phantom: Default::default(), + } + } +} diff --git a/src/domain/orchard_domain_vanilla.rs b/src/domain/orchard_domain_vanilla.rs new file mode 100644 index 000000000..69cd9a54c --- /dev/null +++ b/src/domain/orchard_domain_vanilla.rs @@ -0,0 +1,263 @@ +//! This module implements the note encryption and commitment logic specific for the +//! `OrchardVanilla` flavor. + +use blake2b_simd::Hash as Blake2bHash; +use zcash_note_encryption_zsa::note_bytes::NoteBytesData; + +use crate::{ + bundle::{ + commitments::{ + hasher, ZCASH_ORCHARD_HASH_PERSONALIZATION, ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION, + }, + Authorization, Authorized, + }, + note::{AssetBase, Note}, + orchard_flavor::OrchardVanilla, + Bundle, +}; + +use super::{ + orchard_domain::OrchardDomainCommon, + zcash_note_encryption_domain::{ + build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, NOTE_VERSION_BYTE_V2, + }, +}; + +impl OrchardDomainCommon for OrchardVanilla { + const COMPACT_NOTE_SIZE: usize = COMPACT_NOTE_SIZE_VANILLA; + + type NotePlaintextBytes = NoteBytesData<{ Self::NOTE_PLAINTEXT_SIZE }>; + type NoteCiphertextBytes = NoteBytesData<{ Self::ENC_CIPHERTEXT_SIZE }>; + type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes { + let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V2, note); + + np[COMPACT_NOTE_SIZE_VANILLA..].copy_from_slice(memo); + + NoteBytesData(np) + } + + fn extract_asset(_plaintext: &Self::CompactNotePlaintextBytes) -> Option { + Some(AssetBase::native()) + } + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); + + Self::update_hash_with_actions(&mut h, bundle); + + h.update(&[bundle.flags().to_byte()]); + h.update(&(*bundle.value_balance()).into().to_le_bytes()); + h.update(&bundle.anchor().to_bytes()); + h.finalize() + } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); + h.update(bundle.authorization().proof().as_ref()); + for action in bundle.actions().iter() { + h.update(&<[u8; 64]>::from(action.authorization())); + } + h.update(&<[u8; 64]>::from( + bundle.authorization().binding_signature(), + )); + h.finalize() + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + + use rand::rngs::OsRng; + + use zcash_note_encryption_zsa::{ + note_bytes::NoteBytesData, try_compact_note_decryption, try_note_decryption, + try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, + }; + + use crate::{ + action::Action, + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, + }, + note::{ + testing::arb_native_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, + RandomSeed, Rho, TransmittedNoteCiphertext, + }, + orchard_flavor::OrchardVanilla, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + }; + + use super::super::{ + compact_action::CompactAction, + orchard_domain::OrchardDomain, + zcash_note_encryption_domain::{ + parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard, + }, + }; + + type OrchardDomainVanilla = OrchardDomain; + + /// Implementation of in-band secret distribution for Orchard bundles. + pub type OrchardDomainCommonryptionVanilla = + zcash_note_encryption_zsa::NoteEncryption; + + proptest! { + #[test] + fn encoding_roundtrip( + note in arb_native_note(), + ) { + let memo = &crate::test_vectors::note_encryption_vanilla::test_vectors()[0].memo; + let rho = note.rho(); + + // Encode. + let plaintext = OrchardDomainVanilla::note_plaintext_bytes(¬e, memo); + + // Decode. + let domain = OrchardDomainVanilla::for_rho(rho); + let (compact, parsed_memo) = domain.split_plaintext_at_memo(&plaintext).unwrap(); + + assert!(parse_note_version(compact.as_ref()).is_some()); + + let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::(rho, &compact, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption_vanilla::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); + let rho = Rho::from_nf_old(nf_old); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = AssetBase::native(); + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // nf_old is the nullifier revealed by the receiving Action. + nf_old, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext:: { + epk_bytes: ephemeral_key.0, + enc_ciphertext: NoteBytesData(tv.c_enc), + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomain::for_rho(rho); + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardDomainCommonryptionVanilla::new_with_esk(esk, Some(ovk), note, tv.memo); + + assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/domain/orchard_domain_zsa.rs b/src/domain/orchard_domain_zsa.rs new file mode 100644 index 000000000..0c003de6c --- /dev/null +++ b/src/domain/orchard_domain_zsa.rs @@ -0,0 +1,289 @@ +//! This module implements the note encryption and commitment logic specific for the `OrchardZSA` +//! flavor. + +use blake2b_simd::Hash as Blake2bHash; +use zcash_note_encryption_zsa::note_bytes::NoteBytesData; + +use crate::bundle::commitments::{ + ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION, ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION, +}; +use crate::bundle::Authorized; +use crate::{ + bundle::{ + commitments::{ + hasher, ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION, + ZCASH_ORCHARD_HASH_PERSONALIZATION, ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION, + }, + Authorization, + }, + note::{AssetBase, Note}, + orchard_flavor::OrchardZSA, + Bundle, +}; + +use super::{ + orchard_domain::OrchardDomainCommon, + zcash_note_encryption_domain::{ + build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, COMPACT_NOTE_SIZE_ZSA, + NOTE_VERSION_BYTE_V3, + }, +}; + +impl OrchardDomainCommon for OrchardZSA { + const COMPACT_NOTE_SIZE: usize = COMPACT_NOTE_SIZE_ZSA; + + type NotePlaintextBytes = NoteBytesData<{ Self::NOTE_PLAINTEXT_SIZE }>; + type NoteCiphertextBytes = NoteBytesData<{ Self::ENC_CIPHERTEXT_SIZE }>; + type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes { + let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V3, note); + + np[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA] + .copy_from_slice(¬e.asset().to_bytes()); + np[COMPACT_NOTE_SIZE_ZSA..].copy_from_slice(memo); + + NoteBytesData(np) + } + + fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option { + let bytes = plaintext.as_ref()[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA] + .try_into() + .unwrap(); + + AssetBase::from_bytes(bytes).into() + } + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); + let mut agh = hasher(ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION); + + Self::update_hash_with_actions(&mut agh, bundle); + + agh.update(&[bundle.flags().to_byte()]); + agh.update(&bundle.anchor().to_bytes()); + agh.update(&bundle.expiry_height().to_le_bytes()); + + h.update(agh.finalize().as_bytes()); + + let mut burn_hasher = hasher(ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION); + for burn_item in bundle.burn() { + burn_hasher.update(&burn_item.0.to_bytes()); + burn_hasher.update(&burn_item.1.to_bytes()); + } + h.update(burn_hasher.finalize().as_bytes()); + + h.update(&(*bundle.value_balance()).into().to_le_bytes()); + h.finalize() + } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); + let mut agh = hasher(ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION); + agh.update(bundle.authorization().proof().as_ref()); + for action in bundle.actions().iter() { + agh.update(&<[u8; 64]>::from(action.authorization())); + } + h.update(agh.finalize().as_bytes()); + h.update(&<[u8; 64]>::from( + bundle.authorization().binding_signature(), + )); + h.finalize() + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + + use rand::rngs::OsRng; + + use zcash_note_encryption_zsa::{ + note_bytes::NoteBytesData, try_compact_note_decryption, try_note_decryption, + try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, + }; + + use crate::{ + action::Action, + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, + }, + note::{ + testing::arb_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, + Rho, TransmittedNoteCiphertext, + }, + orchard_flavor::OrchardZSA, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + }; + + use super::super::{ + compact_action::CompactAction, + orchard_domain::OrchardDomain, + zcash_note_encryption_domain::{ + parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard, + }, + }; + + type OrchardDomainZSA = OrchardDomain; + + /// Implementation of in-band secret distribution for Orchard bundles. + pub type OrchardDomainCommonryptionZSA = + zcash_note_encryption_zsa::NoteEncryption; + + proptest! { + #[test] + fn encoding_roundtrip( + note in arb_note(NoteValue::from_raw(100)), + ) { + let memo = &crate::test_vectors::note_encryption_zsa::test_vectors()[0].memo; + let rho = note.rho(); + + // Encode. + let plaintext = OrchardDomainZSA::note_plaintext_bytes(¬e, memo); + + // Decode. + let domain = OrchardDomainZSA::for_rho(rho); + let (compact, parsed_memo) = domain.split_plaintext_at_memo(&plaintext).unwrap(); + + assert!(parse_note_version(compact.as_ref()).is_some()); + + let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::(rho, &compact, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption_zsa::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); + let rho = Rho::from_nf_old(nf_old); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = AssetBase::from_bytes(&tv.asset).unwrap(); + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // nf_old is the nullifier revealed by the receiving Action. + nf_old, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext:: { + epk_bytes: ephemeral_key.0, + enc_ciphertext: NoteBytesData(tv.c_enc), + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomain::for_rho(rho); + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardDomainCommonryptionZSA::new_with_esk(esk, Some(ovk), note, tv.memo); + + assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/domain/zcash_note_encryption_domain.rs b/src/domain/zcash_note_encryption_domain.rs new file mode 100644 index 000000000..91d4ba4f2 --- /dev/null +++ b/src/domain/zcash_note_encryption_domain.rs @@ -0,0 +1,295 @@ +//! This module implements `Domain` and `BatchDomain` traits from the `zcash_note_encryption` +//! crate and contains the common logic for `OrchardVanilla` and `OrchardZSA` flavors. + +use blake2b_simd::Hash; +use group::ff::PrimeField; + +use blake2b_simd::Params; + +use zcash_note_encryption_zsa::{ + note_bytes::NoteBytes, BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, + OutgoingCipherKey, OUT_PLAINTEXT_SIZE, +}; + +use crate::{ + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, + OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, + }, + note::{ExtractedNoteCommitment, Note, RandomSeed, Rho}, + value::{NoteValue, ValueCommitment}, +}; + +use super::orchard_domain::{OrchardDomain, OrchardDomainCommon}; + +const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; + +const NOTE_VERSION_SIZE: usize = 1; +const NOTE_DIVERSIFIER_SIZE: usize = 11; +const NOTE_VALUE_SIZE: usize = 8; +const NOTE_RSEED_SIZE: usize = 32; // rseed (or rcm prior to ZIP 212) + +const NOTE_VERSION_OFFSET: usize = 0; +const NOTE_DIVERSIFIER_OFFSET: usize = NOTE_VERSION_OFFSET + NOTE_VERSION_SIZE; +const NOTE_VALUE_OFFSET: usize = NOTE_DIVERSIFIER_OFFSET + NOTE_DIVERSIFIER_SIZE; +const NOTE_RSEED_OFFSET: usize = NOTE_VALUE_OFFSET + NOTE_VALUE_SIZE; + +/// The size of a Vanilla compact note. +pub(super) const COMPACT_NOTE_SIZE_VANILLA: usize = + NOTE_VERSION_SIZE + NOTE_DIVERSIFIER_SIZE + NOTE_VALUE_SIZE + NOTE_RSEED_SIZE; + +/// The size of the encoding of a ZSA asset id. +const ZSA_ASSET_SIZE: usize = 32; + +/// The size of a ZSA compact note. +pub(super) const COMPACT_NOTE_SIZE_ZSA: usize = COMPACT_NOTE_SIZE_VANILLA + ZSA_ASSET_SIZE; + +/// The version byte for Vanilla. +pub(super) const NOTE_VERSION_BYTE_V2: u8 = 0x02; + +/// The version byte for ZSA. +pub(super) const NOTE_VERSION_BYTE_V3: u8 = 0x03; + +/// The size of the memo. +pub(crate) const MEMO_SIZE: usize = 512; + +pub(super) type Memo = [u8; MEMO_SIZE]; + +/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. +/// +/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs +pub(super) fn prf_ock_orchard( + ovk: &OutgoingViewingKey, + cv: &ValueCommitment, + cmx_bytes: &[u8; 32], + ephemeral_key: &EphemeralKeyBytes, +) -> OutgoingCipherKey { + OutgoingCipherKey( + Params::new() + .hash_length(32) + .personal(PRF_OCK_ORCHARD_PERSONALIZATION) + .to_state() + .update(ovk.as_ref()) + .update(&cv.to_bytes()) + .update(cmx_bytes) + .update(ephemeral_key.as_ref()) + .finalize() + .as_bytes() + .try_into() + .unwrap(), + ) +} + +/// Retrieves the version of the note plaintext. +/// Returns `Some(u8)` if the version is recognized, otherwise `None`. +pub(super) fn parse_note_version(plaintext: &[u8]) -> Option { + plaintext.first().and_then(|version| match *version { + NOTE_VERSION_BYTE_V2 | NOTE_VERSION_BYTE_V3 => Some(*version), + _ => None, + }) +} + +/// Parses the note plaintext (excluding the memo) and extracts the note and address if valid. +/// Domain-specific requirements: +/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. +pub(super) fn parse_note_plaintext_without_memo( + rho: Rho, + plaintext: &D::CompactNotePlaintextBytes, + get_validated_pk_d: F, +) -> Option<(Note, Address)> +where + F: FnOnce(&Diversifier) -> Option, +{ + parse_note_version(plaintext.as_ref())?; + + // The unwraps below are guaranteed to succeed + let diversifier = Diversifier::from_bytes( + plaintext.as_ref()[NOTE_DIVERSIFIER_OFFSET..NOTE_VALUE_OFFSET] + .try_into() + .unwrap(), + ); + + let value = NoteValue::from_bytes( + plaintext.as_ref()[NOTE_VALUE_OFFSET..NOTE_RSEED_OFFSET] + .try_into() + .unwrap(), + ); + + let rseed = Option::from(RandomSeed::from_bytes( + plaintext.as_ref()[NOTE_RSEED_OFFSET..COMPACT_NOTE_SIZE_VANILLA] + .try_into() + .unwrap(), + &rho, + ))?; + + let pk_d = get_validated_pk_d(&diversifier)?; + let recipient = Address::from_parts(diversifier, pk_d); + let asset = D::extract_asset(plaintext)?; + let note = Option::from(Note::from_parts(recipient, value, asset, rho, rseed))?; + + Some((note, recipient)) +} + +// Constructs a note plaintext bytes array given note information. +pub(super) fn build_base_note_plaintext_bytes( + version: u8, + note: &Note, +) -> [u8; NOTE_PLAINTEXT_SIZE] { + let mut np = [0; NOTE_PLAINTEXT_SIZE]; + + np[NOTE_VERSION_OFFSET] = version; + np[NOTE_DIVERSIFIER_OFFSET..NOTE_VALUE_OFFSET] + .copy_from_slice(note.recipient().diversifier().as_array()); + np[NOTE_VALUE_OFFSET..NOTE_RSEED_OFFSET].copy_from_slice(¬e.value().to_bytes()); + np[NOTE_RSEED_OFFSET..COMPACT_NOTE_SIZE_VANILLA].copy_from_slice(note.rseed().as_bytes()); + + np +} + +impl Domain for OrchardDomain { + type EphemeralSecretKey = EphemeralSecretKey; + type EphemeralPublicKey = EphemeralPublicKey; + type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; + type SharedSecret = SharedSecret; + type SymmetricKey = Hash; + type Note = Note; + type Recipient = Address; + type DiversifiedTransmissionKey = DiversifiedTransmissionKey; + type IncomingViewingKey = PreparedIncomingViewingKey; + type OutgoingViewingKey = OutgoingViewingKey; + type ValueCommitment = ValueCommitment; + type ExtractedCommitment = ExtractedNoteCommitment; + type ExtractedCommitmentBytes = [u8; 32]; + type Memo = Memo; + + type NotePlaintextBytes = D::NotePlaintextBytes; + type NoteCiphertextBytes = D::NoteCiphertextBytes; + type CompactNotePlaintextBytes = D::CompactNotePlaintextBytes; + type CompactNoteCiphertextBytes = D::CompactNoteCiphertextBytes; + + fn derive_esk(note: &Self::Note) -> Option { + Some(note.esk()) + } + + fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { + *note.recipient().pk_d() + } + + fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { + PreparedEphemeralPublicKey::new(epk) + } + + fn ka_derive_public( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> Self::EphemeralPublicKey { + esk.derive_public(note.recipient().g_d()) + } + + fn ka_agree_enc( + esk: &Self::EphemeralSecretKey, + pk_d: &Self::DiversifiedTransmissionKey, + ) -> Self::SharedSecret { + esk.agree(pk_d) + } + + fn ka_agree_dec( + ivk: &Self::IncomingViewingKey, + epk: &Self::PreparedEphemeralPublicKey, + ) -> Self::SharedSecret { + epk.agree(ivk) + } + + fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { + secret.kdf_orchard(ephemeral_key) + } + + fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> D::NotePlaintextBytes { + D::build_note_plaintext_bytes(note, memo) + } + + fn derive_ock( + ovk: &Self::OutgoingViewingKey, + cv: &Self::ValueCommitment, + cmstar_bytes: &Self::ExtractedCommitmentBytes, + ephemeral_key: &EphemeralKeyBytes, + ) -> OutgoingCipherKey { + prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) + } + + fn outgoing_plaintext_bytes( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> OutPlaintextBytes { + let mut op = [0; OUT_PLAINTEXT_SIZE]; + op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); + op[32..].copy_from_slice(&esk.0.to_repr()); + OutPlaintextBytes(op) + } + + fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { + epk.to_bytes() + } + + fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { + EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() + } + + fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { + note.commitment().into() + } + + fn parse_note_plaintext_without_memo_ivk( + &self, + ivk: &Self::IncomingViewingKey, + plaintext: &D::CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + parse_note_plaintext_without_memo::(self.rho, plaintext, |diversifier| { + Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) + }) + } + + fn parse_note_plaintext_without_memo_ovk( + &self, + pk_d: &Self::DiversifiedTransmissionKey, + plaintext: &D::CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + parse_note_plaintext_without_memo::(self.rho, plaintext, |_| Some(*pk_d)) + } + + fn split_plaintext_at_memo( + &self, + plaintext: &D::NotePlaintextBytes, + ) -> Option<(Self::CompactNotePlaintextBytes, Self::Memo)> { + let (compact, memo) = plaintext.as_ref().split_at(D::COMPACT_NOTE_SIZE); + Some(( + Self::CompactNotePlaintextBytes::from_slice(compact)?, + memo.try_into().ok()?, + )) + } + + fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { + DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() + } + + fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { + EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) + .into() + } +} + +impl BatchDomain for OrchardDomain { + fn batch_kdf<'a>( + items: impl Iterator, &'a EphemeralKeyBytes)>, + ) -> Vec> { + let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); + + SharedSecret::batch_to_affine(shared_secrets) + .zip(ephemeral_keys) + .map(|(secret, ephemeral_key)| { + secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) + }) + .collect() + } +} diff --git a/src/issuance.rs b/src/issuance.rs new file mode 100644 index 000000000..531db1811 --- /dev/null +++ b/src/issuance.rs @@ -0,0 +1,2070 @@ +//! Issuance logic for Zcash Shielded Assets (ZSAs). +//! +//! This module defines structures and methods for creating, authorizing, and verifying +//! issuance bundles, which introduce new shielded assets into the Orchard protocol. +//! +//! The core components include: +//! - `IssueBundle`: Represents a collection of issuance actions with authorization states. +//! - `IssueAction`: Defines an individual issuance event, including asset details and notes. +//! - `IssueAuth` variants: Track issuance states from creation to finalization. +//! - `verify_issue_bundle`: Ensures issuance validity and prevents unauthorized asset creation. +//! +//! Errors related to issuance, such as invalid signatures or supply overflows, +//! are handled through the `Error` enum. + +use blake2b_simd::Hash as Blake2bHash; +use group::Group; +use k256::schnorr; +use nonempty::NonEmpty; +use rand::RngCore; +use std::collections::HashMap; +use std::fmt; + +use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; +use crate::constants::reference_keys::ReferenceKeys; +use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; +use crate::note::asset_base::is_asset_desc_of_valid_size; +use crate::note::{AssetBase, Nullifier, Rho}; + +use crate::value::NoteValue; +use crate::{Address, Note}; + +use crate::asset_record::AssetRecord; + +use Error::{ + AssetBaseCannotBeIdentityPoint, CannotBeFirstIssuance, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueActionWithoutNoteNotFinalized, + IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, + MissingReferenceNoteOnFirstIssuance, ValueOverflow, WrongAssetDescSize, +}; + +/// Checks if a given note is a reference note. +/// +/// A reference note satisfies the following conditions: +/// - The note's value is zero. +/// - The note's recipient matches the reference recipient. +fn is_reference_note(note: &Note) -> bool { + note.value() == NoteValue::zero() && note.recipient() == ReferenceKeys::recipient() +} + +/// A bundle of actions to be applied to the ledger. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct IssueBundle { + /// The issuer key for the note being created. + ik: IssuanceValidatingKey, + /// The list of issue actions that make up this bundle. + actions: NonEmpty, + /// The authorization for this action. + authorization: T, +} + +/// An issue action applied to the global ledger. +/// +/// Externally, this creates new zsa notes (adding a commitment to the global ledger). +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct IssueAction { + /// Asset description for verification. + asset_desc: Vec, + /// The newly issued notes. + notes: Vec, + /// `finalize` will prevent further issuance of the same asset type. + finalize: bool, +} + +/// The parameters required to add a Note into an IssueAction. +#[derive(Debug)] +pub struct IssueInfo { + /// The recipient of the funds. + pub recipient: Address, + /// The value of this note. + pub value: NoteValue, +} + +impl IssueAction { + /// Constructs a new `IssueAction`. + pub fn new_with_flags(asset_desc: Vec, notes: Vec, flags: u8) -> Option { + let finalize = match flags { + 0b0000_0000 => false, + 0b0000_0001 => true, + _ => return None, + }; + Some(IssueAction { + asset_desc, + notes, + finalize, + }) + } + + /// Constructs an `IssueAction` from its constituent parts. + pub fn from_parts(asset_desc: Vec, notes: Vec, finalize: bool) -> Self { + IssueAction { + asset_desc, + notes, + finalize, + } + } + + /// Returns the asset description for the note being created. + pub fn asset_desc(&self) -> &[u8] { + &self.asset_desc + } + + /// Returns the issued notes. + pub fn notes(&self) -> &[Note] { + &self.notes + } + + /// Returns whether the asset type was finalized in this action. + pub fn is_finalized(&self) -> bool { + self.finalize + } + + /// Verifies and computes the new asset supply for an `IssueAction`. + /// + /// This function calculates the total value (supply) of the asset by summing the values + /// of all its notes and ensures that all note types are equal. It returns the asset and + /// its supply as a tuple (`AssetBase`, `NoteValue`) or an error if the asset was not + /// properly derived or an overflow occurred during the supply amount calculation. + /// + /// # Arguments + /// + /// * `ik` - A reference to the `IssuanceValidatingKey` used for deriving the asset. + /// + /// # Returns + /// + /// A `Result` containing a tuple with an `AssetBase` and an `NoteValue`, or an `Error`. + /// + /// # Errors + /// + /// This function may return an error in any of the following cases: + /// + /// * `WrongAssetDescSize`: The asset description size is invalid. + /// * `ValueOverflow`: The total amount value of all notes in the `IssueAction` overflows. + /// * `IssueBundleIkMismatchAssetBase`: The provided `ik` is not used to derive the + /// `AssetBase` for **all** internal notes. + /// * `IssueActionWithoutNoteNotFinalized`: The `IssueAction` contains no notes and is not finalized. + fn verify(&self, ik: &IssuanceValidatingKey) -> Result<(AssetBase, NoteValue), Error> { + if !is_asset_desc_of_valid_size(self.asset_desc()) { + return Err(WrongAssetDescSize); + } + + if self.notes.is_empty() && !self.is_finalized() { + return Err(IssueActionWithoutNoteNotFinalized); + } + + let issue_asset = AssetBase::derive(ik, &self.asset_desc); + + // Calculate the value of the asset as a sum of values of all its notes + // and ensure all note types are equal the asset derived from asset_desc and ik. + let value_sum = self + .notes + .iter() + .try_fold(NoteValue::zero(), |value_sum, ¬e| { + //The asset base should not be the identity point of the Pallas curve. + if bool::from(note.asset().cv_base().is_identity()) { + return Err(AssetBaseCannotBeIdentityPoint); + } + + // All assets should be derived correctly + if note.asset() != issue_asset { + return Err(IssueBundleIkMismatchAssetBase); + } + + // The total amount should not overflow + (value_sum + note.value()).ok_or(ValueOverflow) + })?; + + Ok((issue_asset, value_sum)) + } + + /// Serialize `finalize` flag to a byte + #[allow(clippy::bool_to_int_with_if)] + pub fn flags(&self) -> u8 { + if self.finalize { + 0b0000_0001 + } else { + 0b0000_0000 + } + } + + /// Returns the reference note if the first note matches the reference note criteria. + /// + /// A reference note must be the first note in the `notes` vector and satisfy the following: + /// - The note's value is zero. + /// - The note's recipient matches the reference recipient. + pub fn get_reference_note(&self) -> Option<&Note> { + self.notes.first().filter(|note| is_reference_note(note)) + } +} + +/// Defines the authorization type of an Issue bundle. +pub trait IssueAuth: fmt::Debug + Clone {} + +/// Marker for an unsigned bundle with no nullifier and no sighash injected. +#[derive(Debug, Clone)] +pub struct AwaitingNullifier; + +/// Marker for an unsigned bundle with a Nullifier injected. +#[derive(Debug, Clone)] +pub struct AwaitingSighash; + +/// Marker for an unsigned bundle with both Sighash and Nullifier injected. +#[derive(Debug, Clone)] +pub struct Prepared { + sighash: [u8; 32], +} + +/// Marker for an authorized bundle. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Signed { + signature: schnorr::Signature, +} + +impl Signed { + /// Returns the signature for this authorization. + pub fn signature(&self) -> &schnorr::Signature { + &self.signature + } + + /// Constructs a `Signed` from a byte array containing Schnorr signature bytes. + pub fn from_data(data: [u8; 64]) -> Self { + Signed { + signature: schnorr::Signature::try_from(data.as_ref()).unwrap(), + } + } +} + +impl IssueAuth for AwaitingNullifier {} +impl IssueAuth for AwaitingSighash {} +impl IssueAuth for Prepared {} +impl IssueAuth for Signed {} + +impl IssueBundle { + /// Returns the issuer verification key for the bundle. + pub fn ik(&self) -> &IssuanceValidatingKey { + &self.ik + } + /// Return the actions for a given `IssueBundle`. + pub fn actions(&self) -> &NonEmpty { + &self.actions + } + /// Return the notes from all actions for a given `IssueBundle`. + pub fn get_all_notes(&self) -> Vec<&Note> { + self.actions.iter().flat_map(|a| a.notes.iter()).collect() + } + + /// Returns the authorization for this action. + pub fn authorization(&self) -> &T { + &self.authorization + } + + /// Find the action corresponding to the `asset_desc` for a given `IssueBundle`. + /// + /// # Returns + /// + /// If a single matching action is found, it is returned as `Some(&IssueAction)`. + /// If no action matches the given `asset_desc`, it returns `None`. + /// + /// # Panics + /// + /// Panics if multiple matching actions are found. + pub fn get_action_by_desc(&self, asset_desc: &[u8]) -> Option<&IssueAction> { + let issue_actions: Vec<&IssueAction> = self + .actions + .iter() + .filter(|a| a.asset_desc.eq(asset_desc)) + .collect(); + match issue_actions.len() { + 0 => None, + 1 => Some(issue_actions[0]), + _ => panic!("Multiple IssueActions with the same asset_desc"), + } + } + + /// Find the actions corresponding to an Asset Base `asset` for a given `IssueBundle`. + /// + /// # Returns + /// + /// Returns `Some(&IssueAction)` if a single matching action is found. + /// Returns `None` if no action matches the given asset base. + /// + /// # Panics + /// + /// Panics if multiple matching actions are found. + pub fn get_action_by_asset(&self, asset: &AssetBase) -> Option<&IssueAction> { + let issue_actions: Vec<&IssueAction> = self + .actions + .iter() + .filter(|a| AssetBase::derive(&self.ik, &a.asset_desc).eq(asset)) + .collect(); + match issue_actions.len() { + 0 => None, + 1 => Some(issue_actions[0]), + _ => panic!("Multiple IssueActions with the same AssetBase"), + } + } + + /// Computes a commitment to the effects of this bundle, suitable for inclusion within + /// a transaction ID. + pub fn commitment(&self) -> IssueBundleCommitment { + IssueBundleCommitment(hash_issue_bundle_txid_data(self)) + } + + /// Constructs an `IssueBundle` from its constituent parts. + pub fn from_parts( + ik: IssuanceValidatingKey, + actions: NonEmpty, + authorization: T, + ) -> Self { + IssueBundle { + ik, + actions, + authorization, + } + } + + /// Transitions this bundle from one authorization state to another. + pub fn map_authorization( + self, + map_auth: impl FnOnce(T) -> T2, + ) -> IssueBundle { + let authorization = self.authorization; + IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: map_auth(authorization), + } + } +} + +impl IssueBundle { + /// Constructs a new `IssueBundle`. + /// + /// If issue_info is None, the new `IssueBundle` will contain one `IssueAction` without notes + /// and with `finalize` set to true. + /// Otherwise, the new `IssueBundle` will contain one `IssueAction` with one note created from + /// issue_info values and with `finalize` set to false. In this created note, rho will be + /// set to zero. The rho value will be updated later by calling the `update_rho` method. + /// + /// If `first_issuance` is true, the `IssueBundle` will contain a reference note for the asset + /// defined by (`asset_desc`, `ik`). + /// + /// # Errors + /// + /// This function may return an error in any of the following cases: + /// + /// * `WrongAssetDescSize`: The `asset_desc` is empty or longer than 512 bytes. + pub fn new( + ik: IssuanceValidatingKey, + asset_desc: Vec, + issue_info: Option, + first_issuance: bool, + mut rng: impl RngCore, + ) -> Result<(IssueBundle, AssetBase), Error> { + if !is_asset_desc_of_valid_size(&asset_desc) { + return Err(WrongAssetDescSize); + } + + let asset = AssetBase::derive(&ik, &asset_desc); + + let mut notes = vec![]; + if first_issuance { + notes.push(create_reference_note(asset, &mut rng)); + }; + + let action = match issue_info { + None => IssueAction { + asset_desc, + notes, + finalize: true, + }, + Some(issue_info) => { + let note = Note::new( + issue_info.recipient, + issue_info.value, + asset, + Rho::zero(), + &mut rng, + ); + + notes.push(note); + + IssueAction { + asset_desc, + notes, + finalize: false, + } + } + }; + + Ok(( + IssueBundle { + ik, + actions: NonEmpty::new(action), + authorization: AwaitingNullifier, + }, + asset, + )) + } + + /// Add a new note to the `IssueBundle`. + /// + /// Rho is set to zero. The rho value will be updated later by calling the `update_rho` method. + /// If `first_issuance` is true, we will also add a reference note for the asset defined by + /// (`asset_desc`, `ik`). + /// + /// # Errors + /// + /// This function may return an error in any of the following cases: + /// + /// * `WrongAssetDescSize`: The `asset_desc` is empty or longer than 512 bytes. + pub fn add_recipient( + &mut self, + asset_desc: &[u8], + recipient: Address, + value: NoteValue, + first_issuance: bool, + mut rng: impl RngCore, + ) -> Result { + if !is_asset_desc_of_valid_size(asset_desc) { + return Err(WrongAssetDescSize); + } + + let asset = AssetBase::derive(&self.ik, asset_desc); + + let note = Note::new(recipient, value, asset, Rho::zero(), &mut rng); + + let notes = if first_issuance { + vec![create_reference_note(asset, &mut rng), note] + } else { + vec![note] + }; + + let action = self + .actions + .iter_mut() + .find(|issue_action| issue_action.asset_desc.eq(asset_desc)); + + match action { + Some(action) => { + // Append to an existing IssueAction. + if first_issuance { + // It cannot be first issuance because we have already some notes for this asset. + return Err(CannotBeFirstIssuance); + } + action.notes.extend(notes); + } + None => { + // Insert a new IssueAction. + self.actions.push(IssueAction { + asset_desc: Vec::from(asset_desc), + notes, + finalize: false, + }); + } + }; + + Ok(asset) + } + + /// Finalizes a given `IssueAction` + /// + /// # Panics + /// + /// Panics if `asset_desc` is empty or longer than 512 bytes. + pub fn finalize_action(&mut self, asset_desc: &[u8]) -> Result<(), Error> { + if !is_asset_desc_of_valid_size(asset_desc) { + return Err(WrongAssetDescSize); + } + + match self + .actions + .iter_mut() + .find(|issue_action| issue_action.asset_desc.eq(asset_desc)) + { + Some(issue_action) => { + issue_action.finalize = true; + } + None => { + return Err(IssueActionNotFound); + } + } + + Ok(()) + } + + /// Compute the correct rho value for each note in the bundle according to + /// [ZIP-227: Issuance of Zcash Shielded Assets][zip227]. + /// + /// [zip227]: https://zips.z.cash/zip-0227 + pub fn update_rho(self, first_nullifier: &Nullifier) -> IssueBundle { + let mut bundle = self; + bundle + .actions + .iter_mut() + .enumerate() + .for_each(|(index_action, action)| { + action + .notes + .iter_mut() + .enumerate() + .for_each(|(index_note, note)| { + note.update_rho_for_issuance_note( + first_nullifier, + index_action.try_into().unwrap(), + index_note.try_into().unwrap(), + ); + }); + }); + bundle.map_authorization(|_| AwaitingSighash) + } +} + +impl IssueBundle { + /// Loads the sighash into the bundle, as preparation for signing. + pub fn prepare(self, sighash: [u8; 32]) -> IssueBundle { + IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: Prepared { sighash }, + } + } +} + +fn create_reference_note(asset: AssetBase, mut rng: impl RngCore) -> Note { + Note::new( + ReferenceKeys::recipient(), + NoteValue::zero(), + asset, + Rho::zero(), + &mut rng, + ) +} + +impl IssueBundle { + /// Sign the `IssueBundle`. + /// The call makes sure that the provided `isk` matches the `ik` and the derived `asset` for each note in the bundle. + pub fn sign(self, isk: &IssuanceAuthorizingKey) -> Result, Error> { + let expected_ik: IssuanceValidatingKey = isk.into(); + + // Make sure the `expected_ik` matches the `asset` for all notes. + self.actions.iter().try_for_each(|action| { + action.verify(&expected_ik)?; + Ok(()) + })?; + + // Make sure the signature can be generated. + let signature = isk + .try_sign(&self.authorization.sighash) + .map_err(|_| IssueBundleInvalidSignature)?; + + Ok(IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: Signed { signature }, + }) + } +} + +/// A commitment to a bundle of actions. +/// +/// This commitment is non-malleable, in the sense that a bundle's commitment will only +/// change if the effects of the bundle are altered. +#[derive(Debug)] +pub struct IssueBundleCommitment(pub Blake2bHash); + +impl From for [u8; 32] { + /// Serializes issue bundle commitment as byte array + fn from(commitment: IssueBundleCommitment) -> Self { + // The commitment uses BLAKE2b-256. + commitment.0.as_bytes().try_into().unwrap() + } +} + +/// A commitment to the authorizing data within a bundle of actions. +#[derive(Debug)] +pub struct IssueBundleAuthorizingCommitment(pub Blake2bHash); + +impl IssueBundle { + /// Computes a commitment to the authorizing data within for this bundle. + /// + /// This together with `IssueBundle::commitment` bind the entire bundle. + pub fn authorizing_commitment(&self) -> IssueBundleAuthorizingCommitment { + IssueBundleAuthorizingCommitment(hash_issue_bundle_auth_data(self)) + } +} + +/// Validates an [`IssueBundle`] by performing the following checks: +/// +/// - **IssueBundle Auth signature verification**: +/// - Ensures the signature on the provided `sighash` matches the bundle’s authorization. +/// - **Static IssueAction verification**: +/// - Runs checks using the `IssueAction::verify` method. +/// - **Node global state related verification**: +/// - Ensures the total supply value does not overflow when adding the new amount to the existing supply. +/// - Verifies that the `AssetBase` has not already been finalized. +/// - Requires a reference note for the *first issuance* of an asset; subsequent issuance may omit it. +/// +/// # Arguments +/// +/// * `bundle`: A reference to the [`IssueBundle`] to be validated. +/// * `sighash`: A 32-byte array representing the `sighash` used to verify the bundle's signature. +/// * `get_global_asset_state`: A closure that takes a reference to an [`AssetBase`] and returns an +/// [`Option`], representing the current state of the asset from a global store +/// of previously issued assets. +/// +/// # Returns +/// +/// A `Result` containing a [`HashMap`] upon success, where each key-value +/// pair represents the new or updated state of an asset. The key is an [`AssetBase`], and the value +/// is the corresponding updated [`AssetRecord`]. +/// +/// # Errors +/// +/// * `IssueBundleInvalidSignature`: Signature verification for the provided `sighash` fails. +/// * `ValueOverflow`: adding the new amount to the existing total supply causes an overflow. +/// * `IssueActionPreviouslyFinalizedAssetBase`: An action is attempted on an asset that has +/// already been finalized. +/// * `MissingReferenceNoteOnFirstIssuance`: No reference note is provided for the first +/// issuance of a new asset. +/// * **Other Errors**: Any additional errors returned by the `IssueAction::verify` method are +/// propagated +pub fn verify_issue_bundle( + bundle: &IssueBundle, + sighash: [u8; 32], + get_global_records: impl Fn(&AssetBase) -> Option, +) -> Result, Error> { + bundle + .ik() + .verify(&sighash, bundle.authorization().signature()) + .map_err(|_| IssueBundleInvalidSignature)?; + + bundle + .actions() + .iter() + .try_fold(HashMap::new(), |mut new_records, action| { + let (asset, amount) = action.verify(bundle.ik())?; + + let is_finalized = action.is_finalized(); + let ref_note = action.get_reference_note(); + + let new_asset_record = match new_records + .get(&asset) + .cloned() + .or_else(|| get_global_records(&asset)) + { + // The first issuance of the asset + None => AssetRecord::new( + amount, + is_finalized, + *ref_note.ok_or(MissingReferenceNoteOnFirstIssuance)?, + ), + + // Subsequent issuance of the asset + Some(current_record) => { + let amount = (current_record.amount + amount).ok_or(ValueOverflow)?; + + if current_record.is_finalized { + return Err(IssueActionPreviouslyFinalizedAssetBase); + } + + AssetRecord::new(amount, is_finalized, current_record.reference_note) + } + }; + + new_records.insert(asset, new_asset_record); + + Ok(new_records) + }) +} + +/// Errors produced during the issuance process +#[derive(Debug, PartialEq, Eq)] +pub enum Error { + /// The requested IssueAction not exists in the bundle. + IssueActionNotFound, + /// The provided `isk` and the derived `ik` does not match at least one note type. + IssueBundleIkMismatchAssetBase, + /// `asset_desc` should be between 1 and 512 bytes. + WrongAssetDescSize, + /// The `IssueAction` is not finalized but contains no notes. + IssueActionWithoutNoteNotFinalized, + /// The `AssetBase` is the Pallas identity point, which is invalid. + AssetBaseCannotBeIdentityPoint, + /// It cannot be first issuance because we have already some notes for this asset. + CannotBeFirstIssuance, + + /// Verification errors: + /// Invalid signature. + IssueBundleInvalidSignature, + /// The provided `AssetBase` has been previously finalized. + IssueActionPreviouslyFinalizedAssetBase, + + /// Overflow error occurred while calculating the value of the asset + ValueOverflow, + + /// No reference note is provided for the first issuance of a new asset. + MissingReferenceNoteOnFirstIssuance, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IssueActionNotFound => { + write!(f, "the requested IssueAction not exists in the bundle.") + } + IssueBundleIkMismatchAssetBase => { + write!( + f, + "the provided `isk` and the derived `ik` do not match at least one note type" + ) + } + WrongAssetDescSize => { + write!(f, "`asset_desc` should be between 1 and 512 bytes") + } + IssueActionWithoutNoteNotFinalized => { + write!( + f, + "this `IssueAction` contains no notes but is not finalized" + ) + } + AssetBaseCannotBeIdentityPoint => { + write!( + f, + "the AssetBase is the identity point of the Pallas curve, which is invalid." + ) + } + CannotBeFirstIssuance => { + write!( + f, + "it cannot be first issuance because we have already some notes for this asset." + ) + } + IssueBundleInvalidSignature => { + write!(f, "invalid signature") + } + IssueActionPreviouslyFinalizedAssetBase => { + write!(f, "the provided `AssetBase` has been previously finalized") + } + ValueOverflow => { + write!( + f, + "overflow error occurred while calculating the value of the asset" + ) + } + MissingReferenceNoteOnFirstIssuance => { + write!( + f, + "no reference note is provided for the first issuance of a new asset." + ) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::{AssetRecord, IssueBundle, IssueInfo}; + use crate::{ + builder::{Builder, BundleType}, + circuit::ProvingKey, + issuance::Error::{ + AssetBaseCannotBeIdentityPoint, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, + IssueBundleInvalidSignature, WrongAssetDescSize, + }, + issuance::{ + is_reference_note, verify_issue_bundle, AwaitingNullifier, IssueAction, Signed, + }, + keys::{ + FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, + SpendAuthorizingKey, SpendingKey, + }, + note::{rho_for_issuance_note, AssetBase, ExtractedNoteCommitment, Nullifier, Rho}, + orchard_flavor::OrchardZSA, + tree::{MerkleHashOrchard, MerklePath}, + value::NoteValue, + Address, Bundle, Note, + }; + use bridgetree::BridgeTree; + use group::{Group, GroupEncoding}; + use nonempty::NonEmpty; + use pasta_curves::pallas::{Point, Scalar}; + use rand::rngs::OsRng; + use rand::RngCore; + use std::collections::HashMap; + + /// Validation for reference note + /// + /// The following checks are performed: + /// - the note value of the reference note is equal to 0 + /// - the recipient of the reference note is equal to the reference recipient + /// - the asset of the reference note is equal to the provided asset + fn verify_reference_note(note: &Note, asset: AssetBase) { + assert!(is_reference_note(note)); + assert_eq!(note.asset(), asset); + } + + #[derive(Clone)] + struct TestParams { + rng: OsRng, + isk: IssuanceAuthorizingKey, + ik: IssuanceValidatingKey, + recipient: Address, + sighash: [u8; 32], + first_nullifier: Nullifier, + } + + fn setup_params() -> TestParams { + let mut rng = OsRng; + + let isk = IssuanceAuthorizingKey::random(); + let ik: IssuanceValidatingKey = (&isk).into(); + + let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng)); + let recipient = fvk.address_at(0u32, Scope::External); + + let mut sighash = [0u8; 32]; + rng.fill_bytes(&mut sighash); + + let first_nullifier = Nullifier::dummy(&mut rng); + + TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } + } + + /// Sets up test parameters for action verification tests. + /// + /// This function generates two notes with the specified values and asset descriptions, + /// and returns the issuance validating key, the asset base, and the issue action. + fn action_verify_test_params( + note1_value: u64, + note2_value: u64, + note1_asset_desc: &[u8], + note2_asset_desc: Option<&[u8]>, // if None, both notes use the same asset + finalize: bool, + ) -> (IssuanceValidatingKey, AssetBase, IssueAction) { + let TestParams { + mut rng, + ik, + recipient, + .. + } = setup_params(); + + let asset = AssetBase::derive(&ik, note1_asset_desc); + let note2_asset = note2_asset_desc.map_or(asset, |desc| AssetBase::derive(&ik, desc)); + + let note1 = Note::new( + recipient, + NoteValue::from_raw(note1_value), + asset, + Rho::zero(), + &mut rng, + ); + + let note2 = Note::new( + recipient, + NoteValue::from_raw(note2_value), + note2_asset, + Rho::zero(), + &mut rng, + ); + + ( + ik, + asset, + IssueAction::from_parts(note1_asset_desc.to_vec(), vec![note1, note2], finalize), + ) + } + + /// This function computes the identity point on the Pallas curve and returns an Asset Base with that value. + fn identity_point() -> AssetBase { + let identity_point = (Point::generator() * -Scalar::one()) + Point::generator(); + AssetBase::from_bytes(&identity_point.to_bytes()).unwrap() + } + + /// Sets up test parameters for identity point tests. + /// + /// This function generates two notes with the identity point as their asset base, + /// and returns the issuance authorizing key, an unauthorized issue bundle containing + /// the notes, and a sighash + fn identity_point_test_params( + note1_value: u64, + note2_value: u64, + ) -> ( + IssuanceAuthorizingKey, + IssueBundle, + [u8; 32], + Nullifier, + ) { + let TestParams { + mut rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let note1 = Note::new( + recipient, + NoteValue::from_raw(note1_value), + identity_point(), + Rho::zero(), + &mut rng, + ); + + let note2 = Note::new( + recipient, + NoteValue::from_raw(note2_value), + identity_point(), + Rho::zero(), + &mut rng, + ); + + let action = + IssueAction::from_parts("arbitrary asset_desc".into(), vec![note1, note2], false); + + let bundle = IssueBundle::from_parts(ik, NonEmpty::new(action), AwaitingNullifier); + + (isk, bundle, sighash, first_nullifier) + } + + #[test] + fn action_verify_valid() { + let (ik, test_asset, action) = action_verify_test_params(10, 20, b"Asset 1", None, false); + + let result = action.verify(&ik); + + assert!(result.is_ok()); + + let (asset, amount) = result.unwrap(); + + assert_eq!(asset, test_asset); + assert_eq!(amount, NoteValue::from_raw(30)); + assert!(!action.is_finalized()); + } + + #[test] + fn action_verify_invalid_for_asset_base_as_identity() { + let (_, bundle, _, _) = identity_point_test_params(10, 20); + + assert_eq!( + bundle.actions.head.verify(&bundle.ik), + Err(AssetBaseCannotBeIdentityPoint) + ); + } + + #[test] + fn action_verify_finalized() { + let (ik, test_asset, action) = action_verify_test_params(10, 20, b"Asset 1", None, true); + + let result = action.verify(&ik); + + assert!(result.is_ok()); + + let (asset, amount) = result.unwrap(); + + assert_eq!(asset, test_asset); + assert_eq!(amount, NoteValue::from_raw(30)); + assert!(action.is_finalized()); + } + + #[test] + fn action_verify_incorrect_asset_base() { + let (ik, _, action) = + action_verify_test_params(10, 20, b"Asset 1", Some(b"Asset 2"), false); + + assert_eq!(action.verify(&ik), Err(IssueBundleIkMismatchAssetBase)); + } + + #[test] + fn action_verify_ik_mismatch_asset_base() { + let (_, _, action) = action_verify_test_params(10, 20, b"Asset 1", None, false); + let TestParams { ik, .. } = setup_params(); + + assert_eq!(action.verify(&ik), Err(IssueBundleIkMismatchAssetBase)); + } + + #[test] + fn issue_bundle_basic() { + let TestParams { + rng, + ik, + recipient, + first_nullifier, + .. + } = setup_params(); + + let str = "Halo".to_string(); + let str2 = "Halo2".to_string(); + + assert_eq!( + IssueBundle::new( + ik.clone(), + vec![b'X'; 513], + Some(IssueInfo { + recipient, + value: NoteValue::unsplittable() + }), + true, + rng, + ) + .unwrap_err(), + WrongAssetDescSize + ); + + assert_eq!( + IssueBundle::new( + ik.clone(), + b"".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::unsplittable() + }), + true, + rng, + ) + .unwrap_err(), + WrongAssetDescSize + ); + + let (mut bundle, asset) = IssueBundle::new( + ik.clone(), + str.clone().into_bytes(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let another_asset = bundle + .add_recipient( + &str.into_bytes(), + recipient, + NoteValue::from_raw(10), + false, + rng, + ) + .unwrap(); + assert_eq!(asset, another_asset); + + let third_asset = bundle + .add_recipient( + str2.as_bytes(), + recipient, + NoteValue::from_raw(15), + true, + rng, + ) + .unwrap(); + assert_ne!(asset, third_asset); + + bundle.actions().iter().for_each(|action| { + action + .notes() + .iter() + .for_each(|note| assert_eq!(note.rho(), Rho::zero())) + }); + let awaiting_sighash_bundle = bundle.update_rho(&first_nullifier); + awaiting_sighash_bundle.actions().iter().for_each(|action| { + action + .notes() + .iter() + .for_each(|note| assert_ne!(note.rho(), Rho::zero())) + }); + + let actions = awaiting_sighash_bundle.actions(); + assert_eq!(actions.len(), 2); + + let action = awaiting_sighash_bundle.get_action_by_asset(&asset).unwrap(); + assert_eq!(action.notes.len(), 3); + let reference_note = action.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset); + let first_note = action.notes.get(1).unwrap(); + assert_eq!(first_note.value().inner(), 5); + assert_eq!(first_note.asset(), asset); + assert_eq!(first_note.recipient(), recipient); + + let second_note = action.notes.get(2).unwrap(); + assert_eq!(second_note.value().inner(), 10); + assert_eq!(second_note.asset(), asset); + assert_eq!(second_note.recipient(), recipient); + + let action2 = awaiting_sighash_bundle + .get_action_by_desc(str2.as_bytes()) + .unwrap(); + assert_eq!(action2.notes.len(), 2); + let reference_note = action2.notes.get(0).unwrap(); + verify_reference_note(reference_note, AssetBase::derive(&ik, str2.as_bytes())); + let first_note = action2.notes().get(1).unwrap(); + assert_eq!(first_note.value().inner(), 15); + assert_eq!(first_note.asset(), third_asset); + + verify_reference_note(action.get_reference_note().unwrap(), asset); + verify_reference_note(action2.get_reference_note().unwrap(), third_asset); + } + + #[test] + fn issue_bundle_finalize_asset() { + let TestParams { + rng, ik, recipient, .. + } = setup_params(); + + let (mut bundle, _) = IssueBundle::new( + ik, + b"NFT".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(u64::MIN), + }), + true, + rng, + ) + .expect("Should properly add recipient"); + + bundle + .finalize_action(b"NFT") + .expect("Should finalize properly"); + + assert_eq!( + bundle.finalize_action(b"Another NFT").unwrap_err(), + IssueActionNotFound + ); + + assert_eq!( + bundle.finalize_action(&vec![b'X'; 513]).unwrap_err(), + WrongAssetDescSize + ); + + assert_eq!(bundle.finalize_action(b"").unwrap_err(), WrongAssetDescSize); + } + + #[test] + fn issue_bundle_prepare() { + let TestParams { + rng, + ik, + recipient, + sighash, + first_nullifier, + .. + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"Frost".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let prepared = bundle.update_rho(&first_nullifier).prepare(sighash); + assert_eq!(prepared.authorization().sighash, sighash); + } + + #[test] + fn issue_bundle_sign() { + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik.clone(), + b"Sign".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + ik.verify(&sighash, &signed.authorization.signature) + .expect("signature should be valid"); + } + + #[test] + fn issue_bundle_invalid_isk_for_signature() { + let TestParams { + rng, + ik, + recipient, + first_nullifier, + .. + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"IssueBundle".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(); + + let err = bundle + .update_rho(&first_nullifier) + .prepare([0; 32]) + .sign(&wrong_isk) + .expect_err("should not be able to sign"); + + assert_eq!(err, IssueBundleIkMismatchAssetBase); + } + + #[test] + fn issue_bundle_incorrect_asset_for_signature() { + let TestParams { + mut rng, + isk, + ik, + recipient, + first_nullifier, + .. + } = setup_params(); + + // Create a bundle with "normal" note + let (mut bundle, _) = IssueBundle::new( + ik, + b"IssueBundle".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(5), + AssetBase::derive(bundle.ik(), b"zsa_asset"), + Rho::zero(), + &mut rng, + ); + bundle.actions.first_mut().notes.push(note); + + let err = bundle + .update_rho(&first_nullifier) + .prepare([0; 32]) + .sign(&isk) + .expect_err("should not be able to sign"); + + assert_eq!(err, IssueBundleIkMismatchAssetBase); + } + + #[test] + fn issue_bundle_verify() { + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik.clone(), + b"Verify".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + let issued_assets = verify_issue_bundle(&signed, sighash, |_| None).unwrap(); + + let first_note = *signed.actions().first().notes().first().unwrap(); + assert_eq!( + issued_assets, + HashMap::from([( + AssetBase::derive(&ik, b"Verify"), + AssetRecord::new(NoteValue::from_raw(5), false, first_note) + )]) + ); + } + + #[test] + fn issue_bundle_verify_with_finalize() { + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (mut bundle, _) = IssueBundle::new( + ik.clone(), + b"Verify with finalize".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(7), + }), + true, + rng, + ) + .unwrap(); + + bundle.finalize_action(b"Verify with finalize").unwrap(); + + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + let issued_assets = verify_issue_bundle(&signed, sighash, |_| None).unwrap(); + + let first_note = *signed.actions().first().notes().first().unwrap(); + assert_eq!( + issued_assets, + HashMap::from([( + AssetBase::derive(&ik, b"Verify with finalize"), + AssetRecord::new(NoteValue::from_raw(7), true, first_note) + )]) + ); + } + + #[test] + fn issue_bundle_verify_with_issued_assets() { + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let asset1_desc = b"Verify with issued assets 1".to_vec(); + let asset2_desc = b"Verify with issued assets 2".to_vec(); + let asset3_desc = b"Verify with issued assets 3".to_vec(); + + let asset1_base = AssetBase::derive(&ik, &asset1_desc); + let asset2_base = AssetBase::derive(&ik, &asset2_desc); + let asset3_base = AssetBase::derive(&ik, &asset3_desc); + + let (mut bundle, _) = IssueBundle::new( + ik, + asset1_desc.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(7), + }), + true, + rng, + ) + .unwrap(); + + bundle + .add_recipient(&asset1_desc, recipient, NoteValue::from_raw(8), false, rng) + .unwrap(); + + bundle.finalize_action(&asset1_desc).unwrap(); + + bundle + .add_recipient(&asset2_desc, recipient, NoteValue::from_raw(10), true, rng) + .unwrap(); + + bundle.finalize_action(&asset2_desc).unwrap(); + + bundle + .add_recipient(&asset3_desc, recipient, NoteValue::from_raw(5), true, rng) + .unwrap(); + + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + let issued_assets = verify_issue_bundle(&signed, sighash, |_| None).unwrap(); + + assert_eq!(issued_assets.keys().len(), 3); + + let reference_note1 = signed.actions()[0].notes()[0]; + let reference_note2 = signed.actions()[1].notes()[0]; + let reference_note3 = signed.actions()[2].notes()[0]; + + assert_eq!( + issued_assets.get(&asset1_base), + Some(&AssetRecord::new( + NoteValue::from_raw(15), + true, + reference_note1 + )) + ); + assert_eq!( + issued_assets.get(&asset2_base), + Some(&AssetRecord::new( + NoteValue::from_raw(10), + true, + reference_note2 + )) + ); + assert_eq!( + issued_assets.get(&asset3_base), + Some(&AssetRecord::new( + NoteValue::from_raw(5), + false, + reference_note3 + )) + ); + } + + #[test] + fn issue_bundle_verify_fail_previously_finalized() { + let TestParams { + mut rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik.clone(), + b"already final".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + let final_type = AssetBase::derive(&ik, b"already final"); + + let issued_assets = [( + final_type, + AssetRecord::new( + NoteValue::from_raw(20), + true, + Note::new( + recipient, + NoteValue::from_raw(10), + final_type, + Rho::zero(), + &mut rng, + ), + ), + )] + .into_iter() + .collect::>(); + + assert_eq!( + verify_issue_bundle(&signed, sighash, |asset| issued_assets.get(asset).copied()) + .unwrap_err(), + IssueActionPreviouslyFinalizedAssetBase + ); + } + + #[test] + fn issue_bundle_verify_fail_bad_signature() { + // we want to inject "bad" signatures for test purposes. + impl IssueBundle { + pub fn set_authorization(&mut self, authorization: Signed) { + self.authorization = authorization; + } + } + + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"bad sig".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(); + + let mut signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + signed.set_authorization(Signed { + signature: wrong_isk.try_sign(&sighash).unwrap(), + }); + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + IssueBundleInvalidSignature + ); + } + + #[test] + fn issue_bundle_verify_fail_wrong_sighash() { + let TestParams { + rng, + isk, + ik, + recipient, + sighash: random_sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"Asset description".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let sighash: [u8; 32] = bundle.commitment().into(); + let signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + assert_eq!( + verify_issue_bundle(&signed, random_sighash, |_| None).unwrap_err(), + IssueBundleInvalidSignature + ); + } + + #[test] + fn issue_bundle_verify_fail_incorrect_asset_description() { + let TestParams { + mut rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"Asset description".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let mut signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(5), + AssetBase::derive(signed.ik(), b"zsa_asset"), + Rho::zero(), + &mut rng, + ); + + signed.actions.first_mut().notes.push(note); + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + IssueBundleIkMismatchAssetBase + ); + } + + #[test] + fn issue_bundle_verify_fail_incorrect_ik() { + let asset_description = b"Asset".to_vec(); + + let TestParams { + mut rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + asset_description.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let mut signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + let incorrect_isk = IssuanceAuthorizingKey::random(); + let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(55), + AssetBase::derive(&incorrect_ik, &asset_description), + Rho::zero(), + &mut rng, + ); + + signed.actions.first_mut().notes = vec![note]; + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + IssueBundleIkMismatchAssetBase + ); + } + + #[test] + fn issue_bundle_verify_fail_wrong_asset_descr_size() { + // we want to inject a "malformed" description for test purposes. + impl IssueAction { + pub fn modify_descr(&mut self, new_descr: Vec) { + self.asset_desc = new_descr; + } + } + + let TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } = setup_params(); + + let (bundle, _) = IssueBundle::new( + ik, + b"Asset description".to_vec(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let mut signed = bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap(); + + // 1. Try a description that is too long + signed.actions.first_mut().modify_descr(vec![b'X'; 513]); + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + WrongAssetDescSize + ); + + // 2. Try a description that is empty + signed.actions.first_mut().modify_descr(b"".to_vec()); + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + WrongAssetDescSize + ); + } + + #[test] + fn issue_bundle_cannot_be_signed_with_asset_base_identity_point() { + let (isk, bundle, sighash, first_nullifier) = identity_point_test_params(10, 20); + + assert_eq!( + bundle + .update_rho(&first_nullifier) + .prepare(sighash) + .sign(&isk) + .unwrap_err(), + AssetBaseCannotBeIdentityPoint + ); + } + + #[test] + fn issue_bundle_verify_fail_asset_base_identity_point() { + let (isk, bundle, sighash, _) = identity_point_test_params(10, 20); + + let signed = IssueBundle { + ik: bundle.ik().clone(), + actions: bundle.actions, + authorization: Signed { + signature: isk.try_sign(&sighash).unwrap(), + }, + }; + + assert_eq!( + verify_issue_bundle(&signed, sighash, |_| None).unwrap_err(), + AssetBaseCannotBeIdentityPoint + ); + } + + #[test] + fn finalize_flag_serialization() { + let mut rng = OsRng; + let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let action = + IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 0u8).unwrap(); + assert_eq!(action.flags(), 0b0000_0000); + + let action = + IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 1u8).unwrap(); + assert_eq!(action.flags(), 0b0000_0001); + + let action = IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 2u8); + assert!(action.is_none()); + } + + #[test] + fn issue_bundle_asset_desc_roundtrip() { + let TestParams { + rng, ik, recipient, .. + } = setup_params(); + + // Generated using https://onlinetools.com/utf8/generate-random-utf8 + let asset_desc_1 = "󅞞 򬪗YV8𱈇m0{둛򙎠[㷊V֤]9Ծ̖l󾓨2닯򗏟iȰ䣄˃Oߺ񗗼🦄" + .to_string() + .as_bytes() + .to_vec(); + + // Not well-formed as per Unicode 15.0 specification, Section 3.9, D92 + let asset_desc_2: Vec = vec![0xc0, 0xaf]; + + // Confirm not valid UTF-8 + assert!(String::from_utf8(asset_desc_2.clone()).is_err()); + + let (mut bundle, asset_base_1) = IssueBundle::new( + ik, + asset_desc_1.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let asset_base_2 = bundle + .add_recipient(&asset_desc_2, recipient, NoteValue::from_raw(10), true, rng) + .unwrap(); + + // Checks for the case of UTF-8 encoded asset description. + let action = bundle.get_action_by_asset(&asset_base_1).unwrap(); + assert_eq!(action.asset_desc(), &asset_desc_1); + let reference_note = action.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset_base_1); + assert_eq!(action.notes.get(1).unwrap().value().inner(), 5); + assert_eq!(bundle.get_action_by_desc(&asset_desc_1).unwrap(), action); + + // Checks for the case on non-UTF-8 encoded asset description. + let action2 = bundle.get_action_by_asset(&asset_base_2).unwrap(); + assert_eq!(action2.asset_desc(), &asset_desc_2); + let reference_note = action2.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset_base_2); + assert_eq!(action2.notes.get(1).unwrap().value().inner(), 10); + assert_eq!(bundle.get_action_by_desc(&asset_desc_2).unwrap(), action2); + } + + #[test] + fn verify_rho_computation_for_issuance_notes() { + // Setup keys + let pk = ProvingKey::build::(); + let sk = SpendingKey::from_bytes([1; 32]).unwrap(); + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + let isk = IssuanceAuthorizingKey::from_bytes([2; 32]).unwrap(); + let ik = IssuanceValidatingKey::from(&isk); + + // Setup note and merkle tree + let mut rng = OsRng; + let asset1 = AssetBase::derive(&ik, b"zsa_asset1"); + let note1 = Note::new( + recipient, + NoteValue::from_raw(10), + asset1, + Rho::from_nf_old(Nullifier::dummy(&mut rng)), + &mut rng, + ); + // Build the merkle tree with only note1 + let mut tree = BridgeTree::::new(100); + let cmx: ExtractedNoteCommitment = note1.commitment().into(); + let leaf = MerkleHashOrchard::from_cmx(&cmx); + tree.append(leaf); + let position = tree.mark().unwrap(); + let root = tree.root(0).unwrap(); + let anchor = root.into(); + let auth_path = tree.witness(position, 0).unwrap(); + let merkle_path = MerklePath::from_parts( + u64::from(position).try_into().unwrap(), + auth_path[..].try_into().unwrap(), + ); + + // Create a transfer bundle + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); + builder.add_spend(fvk, note1, merkle_path).unwrap(); + builder + .add_output(None, recipient, NoteValue::from_raw(5), asset1, None) + .unwrap(); + builder + .add_output(None, recipient, NoteValue::from_raw(5), asset1, None) + .unwrap(); + let unauthorized = builder.build(&mut rng).unwrap().0; + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.create_proof(&pk, &mut rng).unwrap(); + let authorized: Bundle<_, i64, OrchardZSA> = proven + .apply_signatures(rng, sighash, &[SpendAuthorizingKey::from(&sk)]) + .unwrap(); + + // Create an issue bundle + let asset2 = "asset2".to_string(); + let asset3 = "asset3".to_string(); + let (mut bundle, asset) = IssueBundle::new( + ik, + asset2.clone().into_bytes(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + true, + rng, + ) + .unwrap(); + + let another_asset = bundle + .add_recipient( + asset2.as_bytes(), + recipient, + NoteValue::from_raw(10), + false, + rng, + ) + .unwrap(); + assert_eq!(asset, another_asset); + + let third_asset = bundle + .add_recipient( + asset3.as_bytes(), + recipient, + NoteValue::from_raw(10), + true, + rng, + ) + .unwrap(); + assert_ne!(asset, third_asset); + + // Check that all rho values are zero. + bundle.actions().iter().for_each(|action| { + action + .notes() + .iter() + .for_each(|note| assert_eq!(note.rho(), Rho::zero())) + }); + + let awaiting_sighash_bundle = bundle.update_rho(authorized.actions().first().nullifier()); + + assert_eq!(awaiting_sighash_bundle.actions().len(), 2); + assert_eq!( + awaiting_sighash_bundle + .actions() + .get(0) + .unwrap() + .notes() + .len(), + 3 + ); + assert_eq!( + awaiting_sighash_bundle + .actions() + .get(1) + .unwrap() + .notes() + .len(), + 2 + ); + + // Check the rho value for each issuance note in the issue bundle + for (index_action, action) in awaiting_sighash_bundle.actions.iter().enumerate() { + for (index_note, note) in action.notes.iter().enumerate() { + let expected_rho = rho_for_issuance_note( + authorized.actions().first().nullifier(), + index_action.try_into().unwrap(), + index_note.try_into().unwrap(), + ); + assert_eq!(note.rho(), expected_rho); + } + } + } +} + +/// Generators for property testing. +#[cfg(any(test, feature = "test-dependencies"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] +pub mod testing { + use crate::issuance::{AwaitingNullifier, IssueAction, IssueBundle, Prepared, Signed}; + use crate::keys::testing::arb_issuance_validating_key; + use crate::note::asset_base::testing::zsa_asset_base; + use crate::note::testing::arb_zsa_note; + use k256::schnorr; + use nonempty::NonEmpty; + use proptest::collection::vec; + use proptest::prelude::*; + use proptest::prop_compose; + + prop_compose! { + /// Generate a uniformly distributed signature + pub(crate) fn arb_signature()( + sig_bytes in vec(prop::num::u8::ANY, 64) + ) -> schnorr::Signature { + schnorr::Signature::try_from(sig_bytes.as_slice()).unwrap() + } + } + + prop_compose! { + /// Generate an issue action + pub fn arb_issue_action(asset_desc: Vec) + ( + asset in zsa_asset_base(asset_desc.clone()), + ) + ( + note in arb_zsa_note(asset), + )-> IssueAction { + IssueAction{ + asset_desc: asset_desc.clone(), + notes: vec![note], + finalize: false, + } + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. + pub fn arb_awaiting_nullifier_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), + ik in arb_issuance_validating_key() + ) -> IssueBundle { + let actions = NonEmpty::from_vec(actions).unwrap(); + IssueBundle { + ik, + actions, + authorization: AwaitingNullifier + } + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules + pub fn arb_prepared_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), + ik in arb_issuance_validating_key(), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY) + ) -> IssueBundle { + let actions = NonEmpty::from_vec(actions).unwrap(); + IssueBundle { + ik, + actions, + authorization: Prepared { sighash: fake_sighash } + } + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules + pub fn arb_signed_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), + ik in arb_issuance_validating_key(), + fake_sig in arb_signature(), + ) -> IssueBundle { + let actions = NonEmpty::from_vec(actions).unwrap(); + IssueBundle { + ik, + actions, + authorization: Signed { signature: fake_sig }, + } + } + } +} diff --git a/src/keys.rs b/src/keys.rs index 8b85bdcec..d1ba3bb6e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,8 +1,10 @@ //! Key structures for Orchard. -use std::io::{self, Read, Write}; +use std::{ + fmt::{Debug, Formatter}, + io::{self, Read, Write}, +}; -use ::zip32::{AccountId, ChildIndex}; use aes::Aes256; use blake2b_simd::{Hash as Blake2bHash, Params}; use fpe::ff1::{BinaryNumeralString, FF1}; @@ -11,26 +13,40 @@ use group::{ prime::PrimeCurveAffine, Curve, GroupEncoding, }; -use pasta_curves::pallas; -use rand::RngCore; +use k256::{ + schnorr, + schnorr::{ + signature::hazmat::{PrehashSigner, PrehashVerifier}, + Signature, VerifyingKey, + }, + NonZeroScalar, +}; +use pasta_curves::{pallas, pallas::Scalar}; +use rand::{rngs::OsRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; -use zcash_note_encryption::EphemeralKeyBytes; +use zcash_note_encryption_zsa::EphemeralKeyBytes; use crate::{ address::Address, - primitives::redpallas::{self, SpendAuth}, + primitives::redpallas::{self, SpendAuth, VerificationKey}, spec::{ commit_ivk, diversify_hash, extract_p, ka_orchard, ka_orchard_prepared, prf_nf, to_base, to_scalar, NonIdentityPallasPoint, NonZeroPallasBase, NonZeroPallasScalar, PreparedNonIdentityBase, PreparedNonZeroScalar, PrfExpand, }, - zip32::{self, ExtendedSpendingKey}, + zip32::{ + self, ExtendedSpendingKey, ZIP32_ORCHARD_PERSONALIZATION, + ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE, + }, }; -pub use ::zip32::{DiversifierIndex, Scope}; +// Preserve '::' which specifies the EXTERNAL 'zip32' crate +#[rustfmt::skip] +pub use ::zip32::{AccountId, ChildIndex, DiversifierIndex, Scope}; const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; const ZIP32_PURPOSE: u32 = 32; +const ZIP32_PURPOSE_FOR_ISSUANCE: u32 = 227; /// A spending key, from which all key material is derived. /// @@ -105,7 +121,8 @@ impl SpendingKey { ChildIndex::hardened(coin_type), ChildIndex::hardened(account.into()), ]; - ExtendedSpendingKey::from_path(seed, path).map(|esk| esk.sk()) + ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION) + .map(|esk| esk.sk()) } } @@ -138,13 +155,17 @@ impl From<&SpendingKey> for SpendAuthorizingKey { // SpendingKey cannot be constructed such that this assertion would fail. assert!(!bool::from(ask.is_zero())); // TODO: Add TryFrom for SpendAuthorizingKey. - let ret = SpendAuthorizingKey(ask.to_repr().try_into().unwrap()); - // If the last bit of repr_P(ak) is 1, negate ask. - if (<[u8; 32]>::from(SpendValidatingKey::from(&ret).0)[31] >> 7) == 1 { - SpendAuthorizingKey((-ask).to_repr().try_into().unwrap()) - } else { - ret - } + SpendAuthorizingKey(conditionally_negate(ask)) + } +} + +// If the last bit of repr_P(ak) is 1, negate ask. +fn conditionally_negate(scalar: Scalar) -> redpallas::SigningKey { + let ret = redpallas::SigningKey::(scalar.to_repr().try_into().unwrap()); + if (<[u8; 32]>::from(redpallas::VerificationKey::::from(&ret).0)[31] >> 7) == 1 { + redpallas::SigningKey::((-scalar).to_repr().try_into().unwrap()) + } else { + ret } } @@ -184,7 +205,7 @@ impl SpendValidatingKey { self.0.randomize(randomizer) } - /// Converts this spend validating key to its serialized form, + /// Converts this spend key to its serialized form, /// I2LEOSP_256(ak). pub(crate) fn to_bytes(&self) -> [u8; 32] { // This is correct because the wrapped point must have ỹ = 0, and @@ -195,21 +216,143 @@ impl SpendValidatingKey { pub(crate) fn from_bytes(bytes: &[u8]) -> Option { <[u8; 32]>::try_from(bytes) .ok() - .and_then(|b| { - // Structural validity checks for ak_P: - // - The point must not be the identity - // (which for Pallas is canonically encoded as all-zeroes). - // - The sign of the y-coordinate must be positive. - if b != [0; 32] && b[31] & 0x80 == 0 { - >::try_from(b).ok() - } else { - None - } - }) + .and_then(check_structural_validity) .map(SpendValidatingKey) } } +/// A function to check structural validity of the validating keys for authorizing transfers and +/// issuing assets +/// Structural validity checks for ak_P or ik_P: +/// - The point must not be the identity (which for Pallas is canonically encoded as all-zeroes). +/// - The compressed y-coordinate bit must be 0. +fn check_structural_validity( + verification_key_bytes: [u8; 32], +) -> Option> { + if verification_key_bytes != [0; 32] && verification_key_bytes[31] & 0x80 == 0 { + >::try_from(verification_key_bytes).ok() + } else { + None + } +} + +/// An issuance key, from which all key material is derived. +/// +/// $\mathsf{isk}$ as defined in [ZIP 227][issuancekeycomponents]. +/// +/// [issuancekeycomponents]: https://zips.z.cash/zip-0227#issuance-key-derivation +#[derive(Copy, Clone)] +pub struct IssuanceAuthorizingKey(NonZeroScalar); + +impl IssuanceAuthorizingKey { + /// Generates a random issuance key. + /// + /// This is only used when generating a random AssetBase. + /// Real issuance keys should be derived according to [ZIP 32]. + /// + /// [ZIP 32]: https://zips.z.cash/zip-0032 + pub(crate) fn random() -> Self { + IssuanceAuthorizingKey(NonZeroScalar::random(&mut OsRng)) + } + + /// Constructs an Orchard issuance key from uniformly-random bytes. + /// + /// Returns `None` if the bytes do not correspond to a valid Orchard issuance key. + pub fn from_bytes(isk_bytes: [u8; 32]) -> Option { + NonZeroScalar::try_from(&isk_bytes as &[u8]) + .ok() + .map(IssuanceAuthorizingKey) + } + + /// Returns the raw bytes of the issuance key. + /// Unwrap call never fails since the issuance authorizing key is exactly 32 bytes. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes().try_into().unwrap() + } + + /// Derives the Orchard-ZSA issuance key for the given seed, coin type, and account. + pub fn from_zip32_seed( + seed: &[u8], + coin_type: u32, + account: u32, + ) -> Result { + // Call zip32 logic + let path = &[ + ChildIndex::hardened(ZIP32_PURPOSE_FOR_ISSUANCE), + ChildIndex::hardened(coin_type), + ChildIndex::hardened(account), + ]; + + // we are reusing zip32 logic for deriving the key, zip32 should be updated as discussed + let &isk_bytes = + ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE)? + .sk() + .to_bytes(); + + IssuanceAuthorizingKey::from_bytes(isk_bytes).ok_or(zip32::Error::InvalidSpendingKey) + } + + /// Sign the provided message using the `IssuanceAuthorizingKey`. + /// Only supports signing of messages of length 32 bytes, since we will only be using it to sign 32 byte SIGHASH values. + pub fn try_sign(&self, msg: &[u8; 32]) -> Result { + schnorr::SigningKey::from(self.0).sign_prehash(msg) + } +} + +impl Debug for IssuanceAuthorizingKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("IssuanceAuthorizingKey") + .field(&self.0.to_bytes()) + .finish() + } +} + +/// A key used to validate issuance authorization signatures. +/// +/// Defined in [ZIP 227: Issuance of Zcash Shielded Assets § Issuance Key Generation][IssuanceZSA]. +/// +/// [IssuanceZSA]: https://zips.z.cash/zip-0227#issuance-key-derivation +#[derive(Debug, Clone)] +pub struct IssuanceValidatingKey(schnorr::VerifyingKey); + +impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey { + fn from(isk: &IssuanceAuthorizingKey) -> Self { + IssuanceValidatingKey(*schnorr::SigningKey::from(isk.0).verifying_key()) + } +} + +impl PartialEq for IssuanceValidatingKey { + fn eq(&self, other: &Self) -> bool { + self.to_bytes().eq(&other.to_bytes()) + } +} + +impl Eq for IssuanceValidatingKey {} + +impl IssuanceValidatingKey { + /// Converts this issuance validating key to its serialized form, + /// in big-endian order as defined in BIP 340. + /// Unwrap call never fails since the issuance validating key is exactly 32 bytes. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes().try_into().unwrap() + } + + /// Constructs an Orchard issuance validating key from the provided bytes. + /// The bytes are assumed to be encoded in big-endian order. + /// + /// Returns `None` if the bytes do not correspond to a valid key. + pub fn from_bytes(bytes: &[u8]) -> Option { + VerifyingKey::from_bytes(bytes) + .ok() + .map(IssuanceValidatingKey) + } + + /// Verifies a purported `signature` over `msg` made by this verification key. + pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), schnorr::Error> { + self.0.verify_prehash(msg, signature) + } +} + /// A key used to derive [`Nullifier`]s from [`Note`]s. /// /// $\mathsf{nk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. @@ -900,10 +1043,12 @@ impl SharedSecret { #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { + use super::{ + DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, + IssuanceValidatingKey, SpendingKey, + }; use proptest::prelude::*; - use super::{DiversifierIndex, DiversifierKey, EphemeralSecretKey, SpendingKey}; - prop_compose! { /// Generate a uniformly distributed Orchard spending key. pub fn arb_spending_key()( @@ -918,6 +1063,20 @@ pub mod testing { } } + prop_compose! { + /// Generate a uniformly distributed Orchard issuance master key. + pub fn arb_issuance_authorizing_key()( + key in prop::array::uniform32(prop::num::u8::ANY) + .prop_map(IssuanceAuthorizingKey::from_bytes) + .prop_filter( + "Values must correspond to valid Orchard-ZSA issuance keys.", + |opt| opt.is_some() + ) + ) -> IssuanceAuthorizingKey { + key.unwrap() + } + } + prop_compose! { /// Generate a uniformly distributed Orchard ephemeral secret key. pub fn arb_esk()( @@ -949,6 +1108,13 @@ pub mod testing { DiversifierIndex::from(d_bytes) } } + + prop_compose! { + /// Generate a uniformly distributed RedDSA issuance validating key. + pub fn arb_issuance_validating_key()(isk in arb_issuance_authorizing_key()) -> IssuanceValidatingKey { + IssuanceValidatingKey::from(&isk) + } + } } #[cfg(test)] @@ -960,6 +1126,7 @@ mod tests { testing::{arb_diversifier_index, arb_diversifier_key, arb_esk, arb_spending_key}, *, }; + use crate::note::AssetBase; use crate::{ note::{ExtractedNoteCommitment, RandomSeed, Rho}, value::NoteValue, @@ -982,6 +1149,21 @@ mod tests { )); } + #[test] + fn issuance_authorizing_key_from_bytes_fail_on_zero() { + // isk must not be the zero scalar. + let isk = IssuanceAuthorizingKey::from_bytes([0; 32]); + assert!(isk.is_none()); + } + + #[test] + fn issuance_authorizing_key_from_bytes_to_bytes_roundtrip() { + let isk = IssuanceAuthorizingKey::random(); + let isk_bytes = isk.to_bytes(); + let isk_roundtrip = IssuanceAuthorizingKey::from_bytes(isk_bytes).unwrap(); + assert_eq!(isk_bytes, isk_roundtrip.to_bytes()); + } + proptest! { #[test] fn key_agreement( @@ -1019,9 +1201,14 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); + let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap(); + let ak: SpendValidatingKey = (&ask).into(); assert_eq!(<[u8; 32]>::from(ak.0), tv.ak); + let ik: IssuanceValidatingKey = (&isk).into(); + assert_eq!(ik.to_bytes(), tv.ik); + let nk: NullifierDerivingKey = (&sk).into(); assert_eq!(nk.0.to_repr(), tv.nk); @@ -1045,6 +1232,7 @@ mod tests { let note = Note::from_parts( addr, NoteValue::from_raw(tv.note_v), + AssetBase::from_bytes(&tv.asset).unwrap(), rho, RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), ) @@ -1066,4 +1254,22 @@ mod tests { assert_eq!(internal_ovk.0, tv.internal_ovk); } } + + #[test] + fn issuance_auth_sig_test_vectors() { + for tv in crate::test_vectors::issuance_auth_sig::test_vectors() { + let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap(); + + let ik = IssuanceValidatingKey::from(&isk); + assert_eq!(ik.to_bytes(), tv.ik); + + let message = tv.msg; + + let signature = isk.try_sign(&message).unwrap(); + let sig_bytes: [u8; 64] = signature.to_bytes(); + assert_eq!(sig_bytes, tv.sig); + + assert!(ik.verify(&message, &signature).is_ok()); + } + } } diff --git a/src/lib.rs b/src/lib.rs index 005253e97..52387f82c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,13 +18,16 @@ mod action; mod address; +pub mod asset_record; pub mod builder; pub mod bundle; pub mod circuit; mod constants; +pub mod domain; +pub mod issuance; pub mod keys; pub mod note; -pub mod note_encryption; +pub mod orchard_flavor; pub mod primitives; mod spec; pub mod tree; @@ -38,6 +41,7 @@ pub use action::Action; pub use address::Address; pub use bundle::Bundle; pub use circuit::Proof; +pub use constants::reference_keys::ReferenceKeys; pub use constants::MERKLE_DEPTH_ORCHARD as NOTE_COMMITMENT_TREE_DEPTH; pub use note::Note; pub use tree::Anchor; diff --git a/src/note.rs b/src/note.rs index 6a9c70b5a..a08469ef1 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,4 +1,5 @@ //! Data structures used for note construction. +use blake2b_simd::Params; use core::fmt; use memuse::DynamicUsage; @@ -6,9 +7,10 @@ use ff::PrimeField; use group::GroupEncoding; use pasta_curves::pallas; use rand::RngCore; -use subtle::CtOption; +use subtle::{Choice, ConditionallySelectable, CtOption}; use crate::{ + domain::OrchardDomainCommon, keys::{EphemeralSecretKey, FullViewingKey, Scope, SpendingKey}, spec::{to_base, to_scalar, NonZeroPallasScalar, PrfExpand}, value::NoteValue, @@ -21,6 +23,8 @@ pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment}; pub(crate) mod nullifier; pub use self::nullifier::Nullifier; +const ZSA_ISSUE_NOTE_RHO_PERSONALIZATION: &[u8; 16] = b"ZSA_IssueNoteRho"; + /// The randomness used to construct a note. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Rho(pallas::Base); @@ -36,7 +40,7 @@ impl Rho { /// value otherwise. /// /// [`Action::rho`]: crate::action::Action::rho - /// [`CompactAction::rho`]: crate::note_encryption::CompactAction::rho + /// [`CompactAction::rho`]: crate::domain::CompactAction::rho pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { pallas::Base::from_repr(*bytes).map(Rho) } @@ -57,8 +61,17 @@ impl Rho { pub(crate) fn into_inner(self) -> pallas::Base { self.0 } + + /// When creating an issuance note, the rho value is initialized with the Pallas base element zero. + /// This value will be updated later by calling `update_rho` method on the `IssueBundle`. + pub(crate) fn zero() -> Self { + Rho(pallas::Base::zero()) + } } +pub(crate) mod asset_base; +pub use self::asset_base::AssetBase; + /// The ZIP 212 seed randomness for a note. #[derive(Copy, Clone, Debug)] pub struct RandomSeed([u8; 32]); @@ -123,6 +136,17 @@ impl RandomSeed { } } +impl ConditionallySelectable for RandomSeed { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let result: Vec = + a.0.iter() + .zip(b.0.iter()) + .map(|(a_i, b_i)| u8::conditional_select(a_i, b_i, choice)) + .collect(); + RandomSeed(<[u8; 32]>::try_from(result).unwrap()) + } +} + /// A discrete amount of funds received by an address. #[derive(Debug, Copy, Clone)] pub struct Note { @@ -130,6 +154,8 @@ pub struct Note { recipient: Address, /// The value of this note. value: NoteValue, + /// The asset id of this note. + asset: AssetBase, /// A unique creation ID for this note. /// /// This is produced from the nullifier of the note that will be spent in the [`Action`] that @@ -139,6 +165,10 @@ pub struct Note { rho: Rho, /// The seed randomness for various note components. rseed: RandomSeed, + /// The seed randomness for split notes. + /// + /// If it is not a split note, this field is `None`. + rseed_split_note: CtOption, } impl PartialEq for Note { @@ -169,14 +199,17 @@ impl Note { pub fn from_parts( recipient: Address, value: NoteValue, + asset: AssetBase, rho: Rho, rseed: RandomSeed, ) -> CtOption { let note = Note { recipient, value, + asset, rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), }; CtOption::new(note, note.commitment_inner().is_some()) } @@ -189,11 +222,18 @@ impl Note { pub(crate) fn new( recipient: Address, value: NoteValue, + asset: AssetBase, rho: Rho, mut rng: impl RngCore, ) -> Self { loop { - let note = Note::from_parts(recipient, value, rho, RandomSeed::random(&mut rng, &rho)); + let note = Note::from_parts( + recipient, + value, + asset, + rho, + RandomSeed::random(&mut rng, &rho), + ); if note.is_some().into() { break note.unwrap(); } @@ -208,6 +248,7 @@ impl Note { pub(crate) fn dummy( rng: &mut impl RngCore, rho: Option, + asset: AssetBase, ) -> (SpendingKey, FullViewingKey, Self) { let sk = SpendingKey::random(rng); let fvk: FullViewingKey = (&sk).into(); @@ -216,6 +257,7 @@ impl Note { let note = Note::new( recipient, NoteValue::zero(), + asset, rho.unwrap_or_else(|| Rho::from_nf_old(Nullifier::dummy(rng))), rng, ); @@ -233,11 +275,21 @@ impl Note { self.value } + /// Returns the note type of this note. + pub fn asset(&self) -> AssetBase { + self.asset + } + /// Returns the rseed value of this note. pub fn rseed(&self) -> &RandomSeed { &self.rseed } + /// Returns the rseed_split_note value of this note. + pub fn rseed_split_note(&self) -> CtOption { + self.rseed_split_note + } + /// Derives the ephemeral secret key for this note. pub(crate) fn esk(&self) -> EphemeralSecretKey { EphemeralSecretKey(self.rseed.esk(&self.rho)) @@ -274,6 +326,7 @@ impl Note { g_d.to_bytes(), self.recipient.pk_d().to_bytes(), self.value, + self.asset, self.rho.0, self.rseed.psi(&self.rho), self.rseed.rcm(&self.rho), @@ -282,28 +335,78 @@ impl Note { /// Derives the nullifier for this note. pub fn nullifier(&self, fvk: &FullViewingKey) -> Nullifier { + let selected_rseed = self.rseed_split_note.unwrap_or(self.rseed); + Nullifier::derive( fvk.nk(), self.rho.0, - self.rseed.psi(&self.rho), + selected_rseed.psi(&self.rho), self.commitment(), + self.rseed_split_note.is_some(), ) } + + /// Create a split note which has the same values than the input note except for + /// `rseed_split_note` which is equal to a random seed. + pub fn create_split_note(self, rng: &mut impl RngCore) -> Self { + Note { + rseed_split_note: CtOption::new(RandomSeed::random(rng, &self.rho), 1u8.into()), + ..self + } + } + + /// Update the rho value of the issuance note (see + /// [ZIP-227: Issuance of Zcash Shielded Assets][zip227]). + /// + /// [zip227]: https://zips.z.cash/zip-0227 + pub(crate) fn update_rho_for_issuance_note( + &mut self, + nullifier: &Nullifier, + index_action: u32, + index_note: u32, + ) { + self.rho = rho_for_issuance_note(nullifier, index_action, index_note); + } +} + +/// Evaluate the rho value of the issuance note (see +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227]). +/// +/// [zip227]: https://zips.z.cash/zip-0227 +pub(crate) fn rho_for_issuance_note( + nullifier: &Nullifier, + index_action: u32, + index_note: u32, +) -> Rho { + Rho(to_base( + Params::new() + .hash_length(64) + .personal(ZSA_ISSUE_NOTE_RHO_PERSONALIZATION) + .to_state() + .update(&nullifier.to_bytes()) + .update(&[0x84]) + .update(index_action.to_le_bytes().as_ref()) + .update(index_note.to_le_bytes().as_ref()) + .finalize() + .as_bytes() + .try_into() + .unwrap(), + )) } /// An encrypted note. #[derive(Clone)] -pub struct TransmittedNoteCiphertext { +pub struct TransmittedNoteCiphertext { /// The serialization of the ephemeral public key pub epk_bytes: [u8; 32], /// The encrypted note ciphertext - pub enc_ciphertext: [u8; 580], + pub enc_ciphertext: D::NoteCiphertextBytes, /// An encrypted value that allows the holder of the outgoing cipher /// key for the note to recover the note plaintext. pub out_ciphertext: [u8; 80], } -impl fmt::Debug for TransmittedNoteCiphertext { +impl fmt::Debug for TransmittedNoteCiphertext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TransmittedNoteCiphertext") .field("epk_bytes", &self.epk_bytes) @@ -319,10 +422,15 @@ impl fmt::Debug for TransmittedNoteCiphertext { pub mod testing { use proptest::prelude::*; + use crate::note::asset_base::testing::arb_asset_base; + use crate::note::AssetBase; + use crate::value::testing::arb_note_value; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, }; + use subtle::CtOption; + use super::{Note, RandomSeed, Rho}; prop_compose! { @@ -333,17 +441,58 @@ pub mod testing { } prop_compose! { - /// Generate an action without authorization data. + /// Generate an arbitrary note pub fn arb_note(value: NoteValue)( recipient in arb_address(), rho in arb_nullifier().prop_map(Rho::from_nf_old), rseed in arb_rseed(), + asset in arb_asset_base(), + ) -> Note { + Note { + recipient, + value, + asset, + rho, + rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), + } + } + } + + prop_compose! { + /// Generate an arbitrary native note + pub fn arb_native_note()( + recipient in arb_address(), + value in arb_note_value(), + rho in arb_nullifier().prop_map(Rho::from_nf_old), + rseed in arb_rseed(), + ) -> Note { + Note { + recipient, + value, + asset: AssetBase::native(), + rho, + rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()) + } + } + } + + prop_compose! { + /// Generate an arbitrary zsa note + pub fn arb_zsa_note(asset: AssetBase)( + recipient in arb_address(), + value in arb_note_value(), + rho in arb_nullifier().prop_map(Rho::from_nf_old), + rseed in arb_rseed(), ) -> Note { Note { recipient, value, + asset, rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), } } } diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs new file mode 100644 index 000000000..dc00b873a --- /dev/null +++ b/src/note/asset_base.rs @@ -0,0 +1,196 @@ +use blake2b_simd::{Hash as Blake2bHash, Params}; +use group::{Group, GroupEncoding}; +use halo2_proofs::arithmetic::CurveExt; +use pasta_curves::pallas; +use std::hash::{Hash, Hasher}; + +use subtle::{Choice, ConstantTimeEq, CtOption}; + +use crate::constants::fixed_bases::{ + NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, +}; +use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; + +/// Note type identifier. +#[derive(Clone, Copy, Debug, Eq)] +pub struct AssetBase(pallas::Point); + +pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; + +/// Personalization for the ZSA asset digest generator +pub const ZSA_ASSET_DIGEST_PERSONALIZATION: &[u8; 16] = b"ZSA-Asset-Digest"; + +/// AssetDigest for the ZSA asset +/// +/// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][assetdigest]. +/// +/// [assetdigest]: https://zips.z.cash/zip-0226.html#asset-identifiers +pub fn asset_digest(asset_id: Vec) -> Blake2bHash { + Params::new() + .hash_length(64) + .personal(ZSA_ASSET_DIGEST_PERSONALIZATION) + .to_state() + .update(&asset_id) + .finalize() +} + +impl AssetBase { + /// Deserialize the asset_id from a byte array. + pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { + pallas::Point::from_bytes(bytes).map(AssetBase) + } + + /// Serialize the asset_id to its canonical byte representation. + pub fn to_bytes(self) -> [u8; 32] { + self.0.to_bytes() + } + + /// Note type derivation$. + /// + /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][assetbase]. + /// + /// [assetbase]: https://zips.z.cash/zip-0226.html#asset-identifiers + /// + /// # Panics + /// + /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE` or if the derived Asset Base is the identity point. + #[allow(non_snake_case)] + pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &[u8]) -> Self { + assert!( + is_asset_desc_of_valid_size(asset_desc), + "The asset_desc string is not of valid size" + ); + + // EncodeAssetId(ik, asset_desc) = version_byte || ik || asset_desc + let version_byte = [0x00]; + let encode_asset_id = [&version_byte[..], &ik.to_bytes(), asset_desc].concat(); + + let asset_digest = asset_digest(encode_asset_id); + + let asset_base = + pallas::Point::hash_to_curve(ZSA_ASSET_BASE_PERSONALIZATION)(asset_digest.as_bytes()); + + // this will happen with negligible probability. + assert!( + bool::from(!asset_base.is_identity()), + "The Asset Base is the identity point, which is invalid." + ); + + // AssetBase = ZSAValueBase(AssetDigest) + AssetBase(asset_base) + } + + /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. + pub fn native() -> Self { + AssetBase(pallas::Point::hash_to_curve( + VALUE_COMMITMENT_PERSONALIZATION, + )(&NATIVE_ASSET_BASE_V_BYTES[..])) + } + + /// The base point used in value commitments. + pub fn cv_base(&self) -> pallas::Point { + self.0 + } + + /// Whether this note represents a native or ZSA asset. + pub fn is_native(&self) -> Choice { + self.0.ct_eq(&Self::native().0) + } + + /// Generates a ZSA random asset. + /// + /// This is only used in tests. + pub(crate) fn random() -> Self { + let isk = IssuanceAuthorizingKey::random(); + let ik = IssuanceValidatingKey::from(&isk); + let asset_descr = b"zsa_asset".to_vec(); + AssetBase::derive(&ik, &asset_descr) + } +} + +impl Hash for AssetBase { + fn hash(&self, h: &mut H) { + h.write(&self.to_bytes()); + h.finish(); + } +} + +/// Check that `asset_desc` is of valid size. +pub fn is_asset_desc_of_valid_size(asset_desc: &[u8]) -> bool { + !asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE +} + +impl PartialEq for AssetBase { + fn eq(&self, other: &Self) -> bool { + bool::from(self.0.ct_eq(&other.0)) + } +} + +/// Generators for property testing. +#[cfg(any(test, feature = "test-dependencies"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] +pub mod testing { + use super::AssetBase; + + use proptest::prelude::*; + + use crate::keys::{testing::arb_issuance_authorizing_key, IssuanceValidatingKey}; + + prop_compose! { + /// Generate a uniformly distributed note type + pub fn arb_asset_base()( + is_native in prop::bool::ANY, + isk in arb_issuance_authorizing_key(), + asset_desc in prop::collection::vec(any::(), 1..=511), + ) -> AssetBase { + if is_native { + AssetBase::native() + } else { + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) + } + } + } + + prop_compose! { + /// Generate the native note type + pub fn native_asset_base()(_i in 0..1) -> AssetBase { + // TODO: remove _i + AssetBase::native() + } + } + + prop_compose! { + /// Generate an asset ID + pub fn arb_zsa_asset_base()( + isk in arb_issuance_authorizing_key(), + asset_desc in prop::collection::vec(any::(), 1..=511), + ) -> AssetBase { + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) + } + } + + prop_compose! { + /// Generate an asset ID using a specific description + pub fn zsa_asset_base(asset_desc: Vec)( + isk in arb_issuance_authorizing_key(), + ) -> AssetBase { + assert!(super::is_asset_desc_of_valid_size(&asset_desc)); + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::asset_base::test_vectors(); + + for tv in test_vectors { + let calculated_asset_base = AssetBase::derive( + &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), + &tv.description, + ); + let test_vector_asset_base = AssetBase::from_bytes(&tv.asset_base).unwrap(); + + assert_eq!(calculated_asset_base, test_vector_asset_base); + } + } +} diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 9de51d28e..87169049e 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -4,16 +4,20 @@ use bitvec::{array::BitArray, order::Lsb0}; use group::ff::{PrimeField, PrimeFieldBits}; use halo2_gadgets::sinsemilla::primitives as sinsemilla; use pasta_curves::pallas; -use subtle::{ConstantTimeEq, CtOption}; +use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use crate::{ - constants::{fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, L_ORCHARD_BASE}, + constants::{ + fixed_bases::{NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION}, + L_ORCHARD_BASE, + }, + note::asset_base::AssetBase, spec::extract_p, value::NoteValue, }; #[derive(Clone, Debug)] -pub(crate) struct NoteCommitTrapdoor(pub(super) pallas::Scalar); +pub(crate) struct NoteCommitTrapdoor(pub(crate) pallas::Scalar); impl NoteCommitTrapdoor { pub(crate) fn inner(&self) -> pallas::Scalar { @@ -34,28 +38,59 @@ impl NoteCommitment { impl NoteCommitment { /// $NoteCommit^Orchard$. /// - /// Defined in [Zcash Protocol Spec § 5.4.8.4: Sinsemilla commitments][concretesinsemillacommit]. + /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit]. /// - /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit - pub(super) fn derive( + /// [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment + pub(crate) fn derive( g_d: [u8; 32], pk_d: [u8; 32], v: NoteValue, + asset: AssetBase, rho: pallas::Base, psi: pallas::Base, rcm: NoteCommitTrapdoor, ) -> CtOption { - let domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); - domain - .commit( - iter::empty() - .chain(BitArray::<_, Lsb0>::new(g_d).iter().by_vals()) - .chain(BitArray::<_, Lsb0>::new(pk_d).iter().by_vals()) - .chain(v.to_le_bits().iter().by_vals()) - .chain(rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)) - .chain(psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)), - &rcm.0, - ) + let g_d_bits = BitArray::<_, Lsb0>::new(g_d); + let pk_d_bits = BitArray::<_, Lsb0>::new(pk_d); + let v_bits = v.to_le_bits(); + let rho_bits = rho.to_le_bits(); + let psi_bits = psi.to_le_bits(); + + let common_note_bits = iter::empty() + .chain(g_d_bits.iter().by_vals()) + .chain(pk_d_bits.iter().by_vals()) + .chain(v_bits.iter().by_vals()) + .chain(rho_bits.iter().by_vals().take(L_ORCHARD_BASE)) + .chain(psi_bits.iter().by_vals().take(L_ORCHARD_BASE)) + .collect::>(); + + let zec_note_bits = common_note_bits.clone().into_iter(); + + let type_bits = BitArray::<_, Lsb0>::new(asset.to_bytes()); + let zsa_note_bits = common_note_bits + .into_iter() + .chain(type_bits.iter().by_vals()); + + let zec_domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + let zsa_domain = sinsemilla::CommitDomain::new_with_personalization( + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + NOTE_COMMITMENT_PERSONALIZATION, + ); + + let zec_hash_point = zec_domain.hash_to_point(zec_note_bits); + let zsa_hash_point = zsa_domain.hash_to_point(zsa_note_bits); + + // Select the desired hash point in constant-time + let hash_point = zsa_hash_point.and_then(|zsa_hash| { + zec_hash_point.map(|zec_hash| { + pallas::Point::conditional_select(&zsa_hash, &zec_hash, asset.is_native()) + }) + }); + + // To evaluate the commitment from the hash_point, we could use either zec_domain or + // zsa_domain because they have both the same `R` constant. + zec_domain + .commit_from_hash_point(hash_point, &rcm.0) .map(NoteCommitment) } } @@ -112,3 +147,40 @@ impl PartialEq for ExtractedNoteCommitment { } impl Eq for ExtractedNoteCommitment {} + +#[cfg(test)] +mod tests { + use crate::constants::fixed_bases::{ + NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION, + }; + use crate::note::commitment::NoteCommitTrapdoor; + use ff::Field; + use halo2_gadgets::sinsemilla::primitives as sinsemilla; + use pasta_curves::pallas; + use rand::{rngs::OsRng, Rng}; + + #[test] + fn test_commit_in_several_steps() { + let mut os_rng = OsRng::default(); + let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); + + let rcm = NoteCommitTrapdoor(pallas::Scalar::random(&mut os_rng)); + + let domain_zec = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + let domain_zsa = sinsemilla::CommitDomain::new_with_personalization( + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + NOTE_COMMITMENT_PERSONALIZATION, + ); + + let expected_commit = domain_zsa.commit(msg.clone().into_iter(), &rcm.0); + + // Evaluating the commitment in one step with `commit` or in two steps with `hash_to_point` + // and `commit_from_hash_point` must give the same commitment. + let hash_point = domain_zsa.hash_to_point(msg.into_iter()); + let commit_r_zsa = domain_zsa.commit_from_hash_point(hash_point, &rcm.0); + assert_eq!(expected_commit.unwrap(), commit_r_zsa.unwrap()); + + // ZEC and ZSA note commitments must use the same R constant + assert_eq!(domain_zec.R(), domain_zsa.R()); + } +} diff --git a/src/note/nullifier.rs b/src/note/nullifier.rs index bde133995..72a938c89 100644 --- a/src/note/nullifier.rs +++ b/src/note/nullifier.rs @@ -3,10 +3,11 @@ use halo2_proofs::arithmetic::CurveExt; use memuse::DynamicUsage; use pasta_curves::pallas; use rand::RngCore; -use subtle::{ConstantTimeEq, CtOption}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::NoteCommitment; use crate::{ + constants::nullifier_l::nullifier_l, keys::NullifierDerivingKey, spec::{extract_p, mod_r_p}, }; @@ -55,10 +56,17 @@ impl Nullifier { rho: pallas::Base, psi: pallas::Base, cm: NoteCommitment, + is_split_note: Choice, ) -> Self { let k = pallas::Point::hash_to_curve("z.cash:Orchard")(b"K"); - Nullifier(extract_p(&(k * mod_r_p(nk.prf_nf(rho) + psi) + cm.0))) + let nullifier = k * mod_r_p(nk.prf_nf(rho) + psi) + cm.0; + let split_note_nullifier = nullifier + nullifier_l(); + + let selected_nullifier = + pallas::Point::conditional_select(&nullifier, &split_note_nullifier, is_split_note); + + Nullifier(extract_p(&(selected_nullifier))) } } diff --git a/src/note_encryption.rs b/src/note_encryption.rs deleted file mode 100644 index 56d5599cf..000000000 --- a/src/note_encryption.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! In-band secret distribution for Orchard bundles. - -use core::fmt; - -use blake2b_simd::{Hash, Params}; -use group::ff::PrimeField; -use zcash_note_encryption::{ - BatchDomain, Domain, EphemeralKeyBytes, NotePlaintextBytes, OutPlaintextBytes, - OutgoingCipherKey, ShieldedOutput, COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE, NOTE_PLAINTEXT_SIZE, - OUT_PLAINTEXT_SIZE, -}; - -use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, - OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, - }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, - value::{NoteValue, ValueCommitment}, - Address, Note, -}; - -const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; - -/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. -/// -/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs -pub(crate) fn prf_ock_orchard( - ovk: &OutgoingViewingKey, - cv: &ValueCommitment, - cmx_bytes: &[u8; 32], - ephemeral_key: &EphemeralKeyBytes, -) -> OutgoingCipherKey { - OutgoingCipherKey( - Params::new() - .hash_length(32) - .personal(PRF_OCK_ORCHARD_PERSONALIZATION) - .to_state() - .update(ovk.as_ref()) - .update(&cv.to_bytes()) - .update(cmx_bytes) - .update(ephemeral_key.as_ref()) - .finalize() - .as_bytes() - .try_into() - .unwrap(), - ) -} - -fn orchard_parse_note_plaintext_without_memo( - domain: &OrchardDomain, - plaintext: &[u8], - get_pk_d: F, -) -> Option<(Note, Address)> -where - F: FnOnce(&Diversifier) -> DiversifiedTransmissionKey, -{ - assert!(plaintext.len() >= COMPACT_NOTE_SIZE); - - // Check note plaintext version - if plaintext[0] != 0x02 { - return None; - } - - // The unwraps below are guaranteed to succeed by the assertion above - let diversifier = Diversifier::from_bytes(plaintext[1..12].try_into().unwrap()); - let value = NoteValue::from_bytes(plaintext[12..20].try_into().unwrap()); - let rseed = Option::from(RandomSeed::from_bytes( - plaintext[20..COMPACT_NOTE_SIZE].try_into().unwrap(), - &domain.rho, - ))?; - - let pk_d = get_pk_d(&diversifier); - - let recipient = Address::from_parts(diversifier, pk_d); - let note = Option::from(Note::from_parts(recipient, value, domain.rho, rseed))?; - Some((note, recipient)) -} - -/// Orchard-specific note encryption logic. -#[derive(Debug)] -pub struct OrchardDomain { - rho: Rho, -} - -impl memuse::DynamicUsage for OrchardDomain { - fn dynamic_usage(&self) -> usize { - self.rho.dynamic_usage() - } - - fn dynamic_usage_bounds(&self) -> (usize, Option) { - self.rho.dynamic_usage_bounds() - } -} - -impl OrchardDomain { - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_action(act: &Action) -> Self { - Self { rho: act.rho() } - } - - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_compact_action(act: &CompactAction) -> Self { - Self { rho: act.rho() } - } -} - -impl Domain for OrchardDomain { - type EphemeralSecretKey = EphemeralSecretKey; - type EphemeralPublicKey = EphemeralPublicKey; - type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; - type SharedSecret = SharedSecret; - type SymmetricKey = Hash; - type Note = Note; - type Recipient = Address; - type DiversifiedTransmissionKey = DiversifiedTransmissionKey; - type IncomingViewingKey = PreparedIncomingViewingKey; - type OutgoingViewingKey = OutgoingViewingKey; - type ValueCommitment = ValueCommitment; - type ExtractedCommitment = ExtractedNoteCommitment; - type ExtractedCommitmentBytes = [u8; 32]; - type Memo = [u8; 512]; // TODO use a more interesting type - - fn derive_esk(note: &Self::Note) -> Option { - Some(note.esk()) - } - - fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { - *note.recipient().pk_d() - } - - fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { - PreparedEphemeralPublicKey::new(epk) - } - - fn ka_derive_public( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> Self::EphemeralPublicKey { - esk.derive_public(note.recipient().g_d()) - } - - fn ka_agree_enc( - esk: &Self::EphemeralSecretKey, - pk_d: &Self::DiversifiedTransmissionKey, - ) -> Self::SharedSecret { - esk.agree(pk_d) - } - - fn ka_agree_dec( - ivk: &Self::IncomingViewingKey, - epk: &Self::PreparedEphemeralPublicKey, - ) -> Self::SharedSecret { - epk.agree(ivk) - } - - fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { - secret.kdf_orchard(ephemeral_key) - } - - fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> NotePlaintextBytes { - let mut np = [0; NOTE_PLAINTEXT_SIZE]; - np[0] = 0x02; - np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); - np[12..20].copy_from_slice(¬e.value().to_bytes()); - np[20..52].copy_from_slice(note.rseed().as_bytes()); - np[52..].copy_from_slice(memo); - NotePlaintextBytes(np) - } - - fn derive_ock( - ovk: &Self::OutgoingViewingKey, - cv: &Self::ValueCommitment, - cmstar_bytes: &Self::ExtractedCommitmentBytes, - ephemeral_key: &EphemeralKeyBytes, - ) -> OutgoingCipherKey { - prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) - } - - fn outgoing_plaintext_bytes( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> OutPlaintextBytes { - let mut op = [0; OUT_PLAINTEXT_SIZE]; - op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); - op[32..].copy_from_slice(&esk.0.to_repr()); - OutPlaintextBytes(op) - } - - fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { - epk.to_bytes() - } - - fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { - EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() - } - - fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { - note.commitment().into() - } - - fn parse_note_plaintext_without_memo_ivk( - &self, - ivk: &Self::IncomingViewingKey, - plaintext: &[u8], - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - DiversifiedTransmissionKey::derive(ivk, diversifier) - }) - } - - fn parse_note_plaintext_without_memo_ovk( - &self, - pk_d: &Self::DiversifiedTransmissionKey, - plaintext: &NotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, &plaintext.0, |_| *pk_d) - } - - fn extract_memo(&self, plaintext: &NotePlaintextBytes) -> Self::Memo { - plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE] - .try_into() - .unwrap() - } - - fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { - DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() - } - - fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { - EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) - .into() - } -} - -impl BatchDomain for OrchardDomain { - fn batch_kdf<'a>( - items: impl Iterator, &'a EphemeralKeyBytes)>, - ) -> Vec> { - let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); - - SharedSecret::batch_to_affine(shared_secrets) - .zip(ephemeral_keys.into_iter()) - .map(|(secret, ephemeral_key)| { - secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) - }) - .collect() - } -} - -/// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; - -impl ShieldedOutput for Action { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.encrypted_note().epk_bytes) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx().to_bytes() - } - - fn enc_ciphertext(&self) -> &[u8; ENC_CIPHERTEXT_SIZE] { - &self.encrypted_note().enc_ciphertext - } -} - -/// A compact Action for light clients. -#[derive(Clone)] -pub struct CompactAction { - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: [u8; 52], -} - -impl fmt::Debug for CompactAction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "CompactAction") - } -} - -impl From<&Action> for CompactAction { - fn from(action: &Action) -> Self { - CompactAction { - nullifier: *action.nullifier(), - cmx: *action.cmx(), - ephemeral_key: action.ephemeral_key(), - enc_ciphertext: action.encrypted_note().enc_ciphertext[..52] - .try_into() - .unwrap(), - } - } -} - -impl ShieldedOutput for CompactAction { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.ephemeral_key.0) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx.to_bytes() - } - - fn enc_ciphertext(&self) -> &[u8; COMPACT_NOTE_SIZE] { - &self.enc_ciphertext - } -} - -impl CompactAction { - /// Create a CompactAction from its constituent parts - pub fn from_parts( - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: [u8; 52], - ) -> Self { - Self { - nullifier, - cmx, - ephemeral_key, - enc_ciphertext, - } - } - - /// Returns the nullifier of the note being spent. - pub fn nullifier(&self) -> Nullifier { - self.nullifier - } - - /// Returns the commitment to the new note being created. - pub fn cmx(&self) -> ExtractedNoteCommitment { - self.cmx - } - - /// Obtains the [`Rho`] value that was used to construct the new note being created. - pub fn rho(&self) -> Rho { - Rho::from_nf_old(self.nullifier) - } -} - -/// Utilities for constructing test data. -#[cfg(feature = "test-dependencies")] -pub mod testing { - use rand::RngCore; - use zcash_note_encryption::Domain; - - use crate::{ - keys::OutgoingViewingKey, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, - value::NoteValue, - Address, Note, - }; - - use super::{CompactAction, OrchardDomain, OrchardNoteEncryption}; - - /// Creates a fake `CompactAction` paying the given recipient the specified value. - /// - /// Returns the `CompactAction` and the new note. - pub fn fake_compact_action( - rng: &mut R, - nf_old: Nullifier, - recipient: Address, - value: NoteValue, - ovk: Option, - ) -> (CompactAction, Note) { - let rho = Rho::from_nf_old(nf_old); - let rseed = { - loop { - let mut bytes = [0; 32]; - rng.fill_bytes(&mut bytes); - let rseed = RandomSeed::from_bytes(bytes, &rho); - if rseed.is_some().into() { - break rseed.unwrap(); - } - } - }; - let note = Note::from_parts(recipient, value, rho, rseed).unwrap(); - let encryptor = OrchardNoteEncryption::new(ovk, note, [0u8; 512]); - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let ephemeral_key = OrchardDomain::epk_bytes(encryptor.epk()); - let enc_ciphertext = encryptor.encrypt_note_plaintext(); - - ( - CompactAction { - nullifier: nf_old, - cmx, - ephemeral_key, - enc_ciphertext: enc_ciphertext.as_ref()[..52].try_into().unwrap(), - }, - note, - ) - } -} - -#[cfg(test)] -mod tests { - use rand::rngs::OsRng; - use zcash_note_encryption::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, - EphemeralKeyBytes, - }; - - use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; - use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, - OutgoingViewingKey, PreparedIncomingViewingKey, - }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext}, - primitives::redpallas, - value::{NoteValue, ValueCommitment}, - Address, Note, - }; - - #[test] - fn test_vectors() { - let test_vectors = crate::test_vectors::note_encryption::test_vectors(); - - for tv in test_vectors { - // - // Load the test vector components - // - - // Recipient key material - let ivk = PreparedIncomingViewingKey::new( - &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), - ); - let ovk = OutgoingViewingKey::from(tv.ovk); - let d = Diversifier::from_bytes(tv.default_d); - let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); - - // Received Action - let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); - let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); - let rho = Rho::from_nf_old(nf_old); - let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); - - let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); - let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); - - // Details about the expected note - let value = NoteValue::from_raw(tv.v); - let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); - - // - // Test the individual components - // - - let shared_secret = esk.agree(&pk_d); - assert_eq!(shared_secret.to_bytes(), tv.shared_secret); - - let k_enc = shared_secret.kdf_orchard(&ephemeral_key); - assert_eq!(k_enc.as_bytes(), tv.k_enc); - - let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); - assert_eq!(ock.as_ref(), tv.ock); - - let recipient = Address::from_parts(d, pk_d); - let note = Note::from_parts(recipient, value, rho, rseed).unwrap(); - assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); - - let action = Action::from_parts( - // nf_old is the nullifier revealed by the receiving Action. - nf_old, - // We don't need a valid rk for this test. - redpallas::VerificationKey::dummy(), - cmx, - TransmittedNoteCiphertext { - epk_bytes: ephemeral_key.0, - enc_ciphertext: tv.c_enc, - out_ciphertext: tv.c_out, - }, - cv_net.clone(), - (), - ); - - // - // Test decryption - // (Tested first because it only requires immutable references.) - // - - let domain = OrchardDomain { rho }; - - match try_note_decryption(&domain, &ivk, &action) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Note decryption failed"), - } - - match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { - Some((decrypted_note, decrypted_to)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - } - None => panic!("Compact note decryption failed"), - } - - match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Output recovery failed"), - } - - // - // Test encryption - // - - let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, tv.memo); - - assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); - assert_eq!( - &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], - &tv.c_out[..] - ); - } - } -} diff --git a/src/orchard_flavor.rs b/src/orchard_flavor.rs new file mode 100644 index 000000000..a9cc257ae --- /dev/null +++ b/src/orchard_flavor.rs @@ -0,0 +1,35 @@ +//! Defines types and traits for the variations ("flavors") of the Orchard protocol (Vanilla and ZSA). + +use crate::{circuit::OrchardCircuit, domain::OrchardDomainCommon}; + +/// Represents the "Vanilla" variation ("flavor") of the Orchard protocol. +#[derive(Debug, Clone, Default)] +pub struct OrchardVanilla; + +/// Represents the "ZSA" variation ("flavor") of the Orchard protocol. +#[derive(Debug, Clone, Default)] +pub struct OrchardZSA; + +/// Represents the flavor of the Orchard protocol. +/// +/// This enables conditional execution during runtime based on the flavor of the Orchard protocol. +#[derive(Clone, Debug)] +pub enum Flavor { + /// The "Vanilla" flavor of the Orchard protocol. + OrchardVanillaFlavor, + /// The "ZSA" flavor of the Orchard protocol. + OrchardZSAFlavor, +} + +/// A trait binding the common functionality between different Orchard protocol flavors. +pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit { + /// Flavor of the Orchard protocol. + const FLAVOR: Flavor; +} + +impl OrchardFlavor for OrchardVanilla { + const FLAVOR: Flavor = Flavor::OrchardVanillaFlavor; +} +impl OrchardFlavor for OrchardZSA { + const FLAVOR: Flavor = Flavor::OrchardZSAFlavor; +} diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index d19a05048..f51b9e582 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -22,8 +22,8 @@ pub type Binding = reddsa::orchard::Binding; impl SigType for Binding {} /// A RedPallas signing key. -#[derive(Clone, Debug)] -pub struct SigningKey(reddsa::SigningKey); +#[derive(Clone, Copy, Debug)] +pub struct SigningKey(pub(crate) reddsa::SigningKey); impl From> for [u8; 32] { fn from(sk: SigningKey) -> [u8; 32] { @@ -63,7 +63,7 @@ impl SigningKey { /// A RedPallas verification key. #[derive(Clone, Debug)] -pub struct VerificationKey(reddsa::VerificationKey); +pub struct VerificationKey(pub(crate) reddsa::VerificationKey); impl From> for [u8; 32] { fn from(vk: VerificationKey) -> [u8; 32] { @@ -101,7 +101,7 @@ impl Eq for VerificationKey {} impl PartialOrd for VerificationKey { fn partial_cmp(&self, other: &Self) -> Option { - <[u8; 32]>::from(self).partial_cmp(&<[u8; 32]>::from(other)) + Some(self.cmp(other)) } } @@ -154,7 +154,7 @@ impl VerificationKey { } /// A RedPallas signature. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Signature(reddsa::Signature); impl From<[u8; 64]> for Signature { diff --git a/src/spec/prf_expand.rs b/src/spec/prf_expand.rs new file mode 100644 index 000000000..fa7881889 --- /dev/null +++ b/src/spec/prf_expand.rs @@ -0,0 +1,77 @@ +use blake2b_simd::Params; + +const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed"; + +/// The set of domains in which $PRF^\mathsf{expand}$ is defined. +pub(crate) enum PrfExpand { + Esk, + Rcm, + OrchardAsk, + OrchardNk, + OrchardRivk, + Psi, + ZsaIsk, + OrchardZip32Child, + OrchardDkOvk, + OrchardRivkInternal, +} + +impl PrfExpand { + fn domain_separator(&self) -> u8 { + match self { + Self::Esk => 0x04, + Self::Rcm => 0x05, + Self::OrchardAsk => 0x06, + Self::OrchardNk => 0x07, + Self::OrchardRivk => 0x08, + Self::Psi => 0x09, + Self::ZsaIsk => 0x0a, + Self::OrchardZip32Child => 0x81, + Self::OrchardDkOvk => 0x82, + Self::OrchardRivkInternal => 0x83, + } + } + + /// Expands the given secret key in this domain, with no additional data. + /// + /// $PRF^\mathsf{expand}(sk, dst) := BLAKE2b-512("Zcash_ExpandSeed", sk || dst)$ + /// + /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. + /// + /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs + pub(crate) fn expand(self, sk: &[u8]) -> [u8; 64] { + self.with_ad_slices(sk, &[]) + } + + /// Expands the given secret key in this domain, with the given additional data. + /// + /// $PRF^\mathsf{expand}(sk, dst, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || dst || t)$ + /// + /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. + /// + /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs + pub(crate) fn with_ad(self, sk: &[u8], t: &[u8]) -> [u8; 64] { + self.with_ad_slices(sk, &[t]) + } + + /// Expands the given secret key in this domain, with additional data concatenated + /// from the given slices. + /// + /// $PRF^\mathsf{expand}(sk, dst, a, b, ...) := BLAKE2b-512("Zcash_ExpandSeed", sk || dst || a || b || ...)$ + /// + /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. + /// + /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs + pub(crate) fn with_ad_slices(self, sk: &[u8], ts: &[&[u8]]) -> [u8; 64] { + let mut h = Params::new() + .hash_length(64) + .personal(PRF_EXPAND_PERSONALIZATION) + .to_state(); + h.update(sk); + h.update(&[self.domain_separator()]); + for t in ts { + h.update(t); + } + *h.finalize().as_array() + } +} diff --git a/src/test_vectors.rs b/src/test_vectors.rs index 042f3b913..b97f11b04 100644 --- a/src/test_vectors.rs +++ b/src/test_vectors.rs @@ -1,4 +1,7 @@ +pub(crate) mod asset_base; pub(crate) mod commitment_tree; +pub(crate) mod issuance_auth_sig; pub(crate) mod keys; pub(crate) mod merkle_path; -pub(crate) mod note_encryption; +pub(crate) mod note_encryption_vanilla; +pub(crate) mod note_encryption_zsa; diff --git a/src/test_vectors/asset_base.rs b/src/test_vectors/asset_base.rs new file mode 100644 index 000000000..b054359f2 --- /dev/null +++ b/src/test_vectors/asset_base.rs @@ -0,0 +1,1032 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_asset_base) + +pub(crate) struct TestVector { + pub(crate) key: [u8; 32], + pub(crate) description: [u8; 512], + pub(crate) asset_base: [u8; 32], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + key: [ + 0x4b, 0xec, 0xe1, 0xff, 0x00, 0xe2, 0xed, 0x77, 0x64, 0xae, 0x6b, 0xe2, 0x0d, 0x2f, + 0x67, 0x22, 0x04, 0xfc, 0x86, 0xcc, 0xed, 0xd6, 0xfc, 0x1f, 0x71, 0xdf, 0x02, 0xc7, + 0x51, 0x6d, 0x9f, 0x31, + ], + description: [ + 0xc2, 0xb9, 0xc3, 0x8b, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x99, 0xc3, 0xbc, 0xc4, 0xad, + 0xc3, 0x8d, 0xce, 0x89, 0xc8, 0xa1, 0xc7, 0xb1, 0xc4, 0x9d, 0xc4, 0xa0, 0xc3, 0x99, + 0xc7, 0x97, 0xc3, 0xac, 0xc3, 0x8c, 0xe1, 0x9b, 0xa2, 0xc4, 0x86, 0xc4, 0x94, 0x3f, + 0xc7, 0xa6, 0xc4, 0xbb, 0x6a, 0xc2, 0xa6, 0xc7, 0xb4, 0xc6, 0x88, 0xc3, 0x8a, 0xc3, + 0xba, 0xc9, 0x8c, 0xe2, 0xb1, 0xaa, 0xc5, 0x9b, 0xe1, 0x9b, 0xa9, 0xc4, 0xb4, 0xc8, + 0x91, 0xc3, 0x8c, 0xc4, 0x92, 0x30, 0xc5, 0xa9, 0xce, 0x84, 0xc5, 0x90, 0x73, 0xe2, + 0xb1, 0xaa, 0xe2, 0xb1, 0xb8, 0xc5, 0xa3, 0xc3, 0x84, 0xe1, 0x9b, 0x83, 0xc7, 0xb1, + 0xc3, 0xb1, 0xc4, 0x94, 0xc6, 0xbe, 0x69, 0x44, 0xc7, 0xbd, 0xc8, 0xb9, 0xc7, 0x84, + 0xc3, 0xa9, 0xc7, 0x88, 0xc5, 0x8d, 0xc7, 0x91, 0xc9, 0x8a, 0xc3, 0xb9, 0xc4, 0xb1, + 0xc3, 0xb6, 0xc6, 0x82, 0xe1, 0x9b, 0x8f, 0xc4, 0x88, 0xe2, 0xb1, 0xba, 0xc7, 0xb5, + 0x42, 0xc4, 0xa9, 0xc4, 0x90, 0x61, 0xc6, 0x90, 0xc6, 0xb5, 0xc7, 0x9e, 0xc2, 0xb2, + 0xc9, 0x85, 0xc3, 0x9e, 0xc9, 0x84, 0xe2, 0xb1, 0xab, 0xc4, 0x98, 0xe1, 0x9a, 0xa3, + 0xc8, 0x91, 0xe1, 0x9a, 0xbc, 0xc7, 0xba, 0xc3, 0xa9, 0xc7, 0xb1, 0xc4, 0xbf, 0xc8, + 0xa2, 0xc5, 0xb3, 0xc8, 0xa4, 0xc4, 0xb2, 0xc4, 0xb7, 0x45, 0x32, 0xc8, 0x83, 0xc7, + 0xa6, 0xe1, 0x9a, 0xab, 0xc5, 0x88, 0xc8, 0x88, 0xc3, 0x92, 0xe2, 0xb1, 0xac, 0xc9, + 0x8a, 0x25, 0xc8, 0x98, 0xc6, 0xbc, 0xc6, 0xb6, 0x7a, 0xc4, 0xa6, 0xc7, 0xa3, 0xc4, + 0x8f, 0xe1, 0x9a, 0xb0, 0xc2, 0xaf, 0xe1, 0x9b, 0xaf, 0xc3, 0x8c, 0xc2, 0xbf, 0xc5, + 0xb5, 0xe2, 0xb1, 0xa1, 0xe1, 0x9b, 0xa3, 0xc8, 0x8f, 0x6c, 0xc3, 0xa2, 0xc4, 0x8c, + 0xc3, 0xb4, 0xe2, 0xb1, 0xab, 0x7c, 0xc8, 0x93, 0xc9, 0x8c, 0xc6, 0x8d, 0xc9, 0x8c, + 0xc8, 0xb3, 0xc7, 0x96, 0xc7, 0xa0, 0xc7, 0x9f, 0x69, 0xc6, 0x97, 0xc4, 0xbd, 0xe2, + 0xb1, 0xb5, 0xc6, 0xa4, 0xe1, 0x9b, 0x83, 0xe1, 0x9b, 0x83, 0xe2, 0xb1, 0xaa, 0xc7, + 0x85, 0xe2, 0xb1, 0xaf, 0x7d, 0xc6, 0x9b, 0xc2, 0xa5, 0xc7, 0x9c, 0xc5, 0xaf, 0xc7, + 0x97, 0xc8, 0x9e, 0xc3, 0x91, 0xc2, 0xa2, 0xc7, 0x9f, 0xc4, 0xbf, 0x62, 0xc3, 0x8e, + 0xc5, 0xbd, 0xc8, 0xb3, 0xcd, 0xb6, 0xc4, 0x95, 0x39, 0xc3, 0xa4, 0xe1, 0x9b, 0xad, + 0xe1, 0x9b, 0x84, 0xc8, 0xad, 0x42, 0xc8, 0xa1, 0x34, 0xc4, 0xbd, 0x6b, 0xc3, 0x83, + 0xc7, 0xa8, 0x48, 0x5e, 0xc5, 0x97, 0xc8, 0xb5, 0xc6, 0xa4, 0xc6, 0x94, 0xc7, 0x98, + 0xc6, 0xb2, 0xc4, 0x9a, 0x46, 0xc6, 0xad, 0xe1, 0x9b, 0x83, 0xc4, 0x8b, 0x3c, 0xc6, + 0x98, 0xc9, 0x8e, 0xc2, 0xbc, 0xc3, 0x80, 0xc7, 0x83, 0x6f, 0x63, 0xe1, 0x9b, 0xa0, + 0xc4, 0x94, 0xe1, 0x9a, 0xbc, 0xc3, 0xa9, 0xe1, 0x9a, 0xa4, 0xc5, 0x8c, 0xc8, 0x94, + 0xc7, 0xa3, 0xce, 0x87, 0xc9, 0x82, 0xe2, 0xb1, 0xa6, 0xc4, 0x81, 0xc4, 0xa8, 0xc6, + 0xb5, 0xc7, 0x93, 0xe1, 0x9b, 0x8c, 0xc5, 0x87, 0xc4, 0x97, 0xc7, 0x93, 0x4a, 0xc5, + 0x9e, 0xc9, 0x84, 0xe2, 0xb1, 0xa0, 0xc4, 0xab, 0xc7, 0x83, 0xc6, 0x88, 0xc5, 0xaa, + 0xc5, 0xa1, 0xe1, 0x9b, 0x86, 0xc7, 0x82, 0xe2, 0xb1, 0xa5, 0xc3, 0x9e, 0xc7, 0xbc, + 0xc6, 0x8b, 0x46, 0xe1, 0x9a, 0xa9, 0xc6, 0x95, 0xc4, 0xa7, 0xc6, 0x8d, 0xe1, 0x9b, + 0x8d, 0xc7, 0x95, 0xc3, 0xaf, 0xc6, 0x9a, 0xe2, 0xb1, 0xba, 0xc3, 0xaa, 0xc7, 0x82, + 0xe1, 0x9b, 0x9d, 0xc9, 0x80, 0x25, 0xc7, 0x8d, 0x28, 0x46, 0xe2, 0xb1, 0xb5, 0xc6, + 0x8b, 0xe2, 0xb1, 0xb4, 0xc3, 0x85, 0xc8, 0xbe, + ], + asset_base: [ + 0xb2, 0x5c, 0xbe, 0xdd, 0x3c, 0xae, 0xa0, 0x46, 0x24, 0x08, 0x21, 0xa9, 0x22, 0xcd, + 0xae, 0xb7, 0xfe, 0xcc, 0x4f, 0xed, 0x1d, 0x60, 0xc1, 0x61, 0x57, 0x9c, 0xd9, 0xcf, + 0x4e, 0x0c, 0xc9, 0x1f, + ], + }, + TestVector { + key: [ + 0xd5, 0x9a, 0x54, 0xb2, 0x87, 0x10, 0x58, 0xe8, 0xdf, 0x0e, 0x8d, 0xb3, 0x15, 0x6f, + 0xb5, 0x60, 0xd9, 0x8d, 0xa4, 0xdb, 0x99, 0x04, 0x2c, 0xe9, 0x85, 0x2f, 0x4b, 0x08, + 0xb1, 0xf4, 0x9f, 0xaa, + ], + description: [ + 0xe1, 0x9b, 0x93, 0xc6, 0xab, 0xe1, 0x9b, 0x88, 0xc2, 0xb5, 0x24, 0xc6, 0x85, 0xe2, + 0xb1, 0xae, 0xe1, 0x9a, 0xbe, 0xc6, 0x9c, 0xc5, 0xb1, 0xc3, 0xad, 0xc6, 0xaa, 0xc3, + 0xaf, 0xc3, 0x9d, 0xc2, 0xab, 0xc7, 0x9b, 0xc6, 0xad, 0xc3, 0xb3, 0xc7, 0xbe, 0xe1, + 0x9b, 0xac, 0xc7, 0x91, 0xc8, 0x9d, 0xc9, 0x82, 0xc4, 0xae, 0xc4, 0x81, 0xe1, 0x9b, + 0xa8, 0xc6, 0x84, 0xe2, 0xb1, 0xb0, 0xc5, 0x86, 0x61, 0xc6, 0x95, 0xcd, 0xb4, 0xc2, + 0xbd, 0xc6, 0xb4, 0xc4, 0x84, 0xc7, 0x97, 0xe2, 0xb1, 0xb6, 0xc9, 0x8a, 0xe1, 0x9a, + 0xbb, 0xcd, 0xbc, 0xcd, 0xb6, 0xc8, 0xbc, 0xe1, 0x9b, 0xb0, 0xe2, 0xb1, 0xa5, 0xc7, + 0x89, 0xe1, 0x9b, 0x92, 0xc5, 0xad, 0xe2, 0xb1, 0xad, 0xc3, 0x85, 0xe1, 0x9a, 0xbb, + 0xc7, 0xb3, 0xc6, 0xb4, 0xc5, 0xaf, 0xc5, 0x92, 0xe1, 0x9a, 0xb8, 0xc3, 0x88, 0xc2, + 0xb7, 0xe1, 0x9a, 0xab, 0xc8, 0xb2, 0xc7, 0x96, 0xc6, 0xb3, 0xe1, 0x9b, 0x89, 0x31, + 0xe1, 0x9a, 0xa7, 0xc4, 0x89, 0xc4, 0x96, 0x5d, 0xe1, 0x9b, 0xa6, 0xc4, 0x84, 0xc6, + 0x8d, 0xc7, 0xb9, 0xc8, 0x94, 0xe1, 0x9b, 0x8b, 0xc9, 0x8b, 0xc3, 0xb0, 0x44, 0x6f, + 0xce, 0x86, 0x71, 0xc6, 0xb2, 0xe1, 0x9a, 0xbf, 0xc6, 0x80, 0xc5, 0x98, 0xc4, 0xbd, + 0xc6, 0xbb, 0xc7, 0xad, 0xc5, 0xbb, 0x77, 0xc2, 0xb8, 0xc2, 0xb5, 0xc8, 0xbd, 0xc3, + 0xb1, 0xc8, 0x84, 0xcd, 0xb2, 0xc6, 0xa2, 0x7c, 0xc5, 0x81, 0x4f, 0xc5, 0xab, 0xc4, + 0xa5, 0xc4, 0xb6, 0xc3, 0x81, 0xc6, 0xba, 0xc4, 0x84, 0xe2, 0xb1, 0xa8, 0xc4, 0x9e, + 0xe1, 0x9b, 0xae, 0xc5, 0x9a, 0xc5, 0xa2, 0xc2, 0xbe, 0xc8, 0xb9, 0xe2, 0xb1, 0xb2, + 0xe2, 0xb1, 0xb9, 0xc8, 0xa8, 0x2c, 0xe1, 0x9b, 0x9d, 0xc3, 0xaf, 0xc3, 0x98, 0xc4, + 0x9d, 0xe1, 0x9b, 0x85, 0x55, 0xc8, 0x89, 0xc6, 0x8f, 0xc4, 0xb6, 0xc6, 0xab, 0xc6, + 0xaa, 0xc6, 0xb8, 0x32, 0xc4, 0x88, 0xc6, 0x95, 0xc7, 0x93, 0xc6, 0xa1, 0xc2, 0xb3, + 0xc4, 0xb3, 0xc5, 0x80, 0xc5, 0x93, 0x7a, 0xc5, 0xa4, 0x66, 0xc4, 0xa1, 0x47, 0x44, + 0xe1, 0x9a, 0xb5, 0x7d, 0xc6, 0xab, 0xc2, 0xa2, 0xc6, 0x86, 0xc8, 0x8b, 0xc8, 0x8d, + 0xc8, 0xa7, 0xc8, 0xae, 0xc3, 0xb6, 0xc8, 0xac, 0x24, 0x3d, 0xcd, 0xbc, 0xc3, 0x8f, + 0xc5, 0xbb, 0xc8, 0x92, 0xc3, 0xba, 0xc4, 0x84, 0xe1, 0x9a, 0xbb, 0xc5, 0x83, 0x6b, + 0x41, 0xc6, 0xb8, 0xc4, 0x9d, 0xc7, 0x89, 0xe1, 0x9b, 0x9c, 0x45, 0xc7, 0xb0, 0xc2, + 0xa3, 0xe1, 0x9a, 0xa4, 0xc8, 0x94, 0xc8, 0x92, 0xc9, 0x8e, 0x71, 0xc7, 0x8a, 0x5b, + 0xe1, 0x9b, 0xaa, 0xc6, 0xaf, 0xe1, 0x9b, 0xab, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x83, + 0xc8, 0x9f, 0xe2, 0xb1, 0xb6, 0xe1, 0x9a, 0xb7, 0xc2, 0xa7, 0xc4, 0x83, 0x2f, 0xc2, + 0xae, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xa1, 0xe1, 0x9a, 0xbe, 0x66, 0x3b, 0xc8, 0xaf, + 0xc8, 0xbd, 0xc7, 0xb8, 0xc9, 0x8d, 0xc5, 0x89, 0xc5, 0xa5, 0xe1, 0x9a, 0xae, 0xc8, + 0xa1, 0xc6, 0x8b, 0xc2, 0xa5, 0xc9, 0x80, 0xe2, 0xb1, 0xa4, 0xc3, 0xba, 0xe2, 0xb1, + 0xb7, 0xc5, 0x92, 0xc4, 0x9b, 0xc7, 0x87, 0xc6, 0xb5, 0xc5, 0xb3, 0xc6, 0x9c, 0x3c, + 0xc6, 0x9e, 0xc4, 0x9b, 0xc8, 0xa9, 0xc5, 0x8c, 0xe1, 0x9b, 0x90, 0xc7, 0xa8, 0xc7, + 0x9d, 0xc8, 0x9b, 0xc7, 0xb2, 0xe2, 0xb1, 0xae, 0xc6, 0x90, 0xc6, 0x8e, 0x70, 0xe1, + 0x9b, 0xa7, 0x32, 0xc5, 0x85, 0x66, 0xc5, 0xbb, 0xc7, 0xb8, 0xc7, 0x8b, 0xc8, 0xb1, + 0xc8, 0xaa, 0xc5, 0x8c, 0xc8, 0x82, 0xc6, 0xb2, 0xcd, 0xb7, 0xe1, 0x9b, 0x93, 0xc6, + 0x9e, 0xe1, 0x9b, 0x90, 0x4d, 0x70, 0xc8, 0xaf, + ], + asset_base: [ + 0xbd, 0x7f, 0x79, 0xe7, 0xda, 0xdd, 0x1d, 0x48, 0x27, 0x06, 0x04, 0xcd, 0xdb, 0x1d, + 0x65, 0x44, 0x09, 0x29, 0xea, 0x25, 0xe7, 0x7b, 0x72, 0x85, 0x5f, 0xf6, 0xfd, 0x99, + 0x18, 0xa5, 0x91, 0xb6, + ], + }, + TestVector { + key: [ + 0x85, 0xbc, 0x7d, 0x64, 0xbe, 0x0d, 0xef, 0xc4, 0x77, 0xeb, 0x05, 0xe7, 0x95, 0xf7, + 0x69, 0x57, 0x62, 0x80, 0x02, 0x61, 0x62, 0x5a, 0x7b, 0x71, 0xa1, 0x4d, 0x18, 0xf0, + 0xef, 0x1f, 0x01, 0xb0, + ], + description: [ + 0xc7, 0x96, 0xcd, 0xb7, 0xc3, 0x9b, 0xc7, 0x8d, 0xc4, 0x92, 0x7b, 0xcd, 0xb4, 0x34, + 0xc3, 0x84, 0xcd, 0xb6, 0xc2, 0xbc, 0x3d, 0xc6, 0xa7, 0xc8, 0xbc, 0xe1, 0x9b, 0x9f, + 0xc3, 0xbd, 0xc8, 0x9a, 0xc5, 0x81, 0xc4, 0xb7, 0x6c, 0xc5, 0xb3, 0xe1, 0x9a, 0xa5, + 0xe1, 0x9b, 0xa6, 0x44, 0xe1, 0x9b, 0xa4, 0xc5, 0xbc, 0xe1, 0x9b, 0x99, 0xc6, 0x91, + 0xc8, 0x9c, 0xc6, 0x93, 0xc5, 0x95, 0xc4, 0xa2, 0xe2, 0xb1, 0xa2, 0xc8, 0x84, 0x45, + 0xc2, 0xaa, 0x7e, 0xc2, 0xb7, 0xc3, 0x83, 0x66, 0xc4, 0x81, 0xc7, 0x98, 0xc8, 0x83, + 0x2b, 0xc6, 0xad, 0xc7, 0x9c, 0xc4, 0x8b, 0xe2, 0xb1, 0xaa, 0x78, 0xc4, 0xa8, 0xc4, + 0x86, 0xc6, 0x9a, 0xc8, 0xa2, 0x35, 0xc3, 0x81, 0xc6, 0x8f, 0xc6, 0x9b, 0xe1, 0x9b, + 0x93, 0xc6, 0x8c, 0xe1, 0x9b, 0x8e, 0xc4, 0xb1, 0xc6, 0xbc, 0xe2, 0xb1, 0xb3, 0x5a, + 0xc5, 0x98, 0xc6, 0xaa, 0xc4, 0xae, 0xc8, 0xa1, 0xe1, 0x9a, 0xbb, 0xc7, 0xad, 0xc5, + 0xae, 0xc5, 0xaa, 0xc6, 0x85, 0xc2, 0xb2, 0xe1, 0x9b, 0x9e, 0xc7, 0xb4, 0x6b, 0xc4, + 0xaf, 0xc7, 0xa9, 0xc4, 0xa6, 0xc8, 0xa8, 0xc4, 0x9e, 0xcd, 0xb1, 0xc7, 0xad, 0xc3, + 0xb8, 0xc3, 0x81, 0xc3, 0xa4, 0xc8, 0x98, 0xc3, 0xbd, 0xc4, 0xae, 0xe1, 0x9b, 0x84, + 0xc8, 0x8e, 0x6a, 0xc4, 0x96, 0xe1, 0x9a, 0xa6, 0xc6, 0x90, 0xe1, 0x9a, 0xbe, 0xc7, + 0xa1, 0x2b, 0xcd, 0xb2, 0xc8, 0xa5, 0xc7, 0x87, 0xc7, 0x95, 0x32, 0xc8, 0xa8, 0xc9, + 0x85, 0xc5, 0x84, 0xc5, 0x99, 0xc7, 0x9f, 0x63, 0x42, 0xc6, 0xb6, 0x42, 0x79, 0xc7, + 0x90, 0xc5, 0x9d, 0xe2, 0xb1, 0xb7, 0xc4, 0xab, 0xc5, 0xbf, 0xc3, 0xaf, 0x35, 0x49, + 0xc6, 0xb9, 0xe1, 0x9b, 0x88, 0xc5, 0xbe, 0xc3, 0xb1, 0x23, 0xe2, 0xb1, 0xa3, 0xc5, + 0x96, 0xc8, 0x8c, 0xe1, 0x9b, 0xa7, 0xc5, 0xa8, 0xc8, 0x95, 0xc7, 0xa6, 0xc8, 0xa7, + 0xe1, 0x9a, 0xaf, 0xc3, 0xa0, 0xc5, 0x82, 0xc6, 0x83, 0x70, 0xe2, 0xb1, 0xb1, 0xc8, + 0x86, 0xc7, 0xb4, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xb3, 0xc5, 0xa2, 0xc3, 0x96, 0xc3, + 0xbd, 0xc9, 0x87, 0xc2, 0xa5, 0xce, 0x88, 0xc3, 0xa3, 0xe1, 0x9b, 0xa8, 0xc4, 0x8f, + 0xe1, 0x9a, 0xbf, 0xe1, 0x9b, 0x8b, 0xc2, 0xb3, 0xc3, 0xb7, 0xc6, 0xa1, 0xc5, 0x88, + 0xe1, 0x9b, 0xa3, 0xc6, 0xa3, 0xc3, 0x8c, 0xc3, 0xa4, 0xc6, 0xa1, 0xe1, 0x9b, 0x87, + 0xc8, 0xa0, 0xc3, 0x94, 0xc6, 0x9a, 0xc7, 0xb1, 0xc5, 0x85, 0xc6, 0xbf, 0xc8, 0x91, + 0xc6, 0x88, 0xc4, 0x9e, 0xc6, 0x9a, 0xcd, 0xb1, 0xc4, 0xa6, 0xc6, 0xb0, 0xc3, 0xbc, + 0x23, 0xc4, 0x9b, 0xc3, 0xa4, 0xc8, 0xb3, 0xe2, 0xb1, 0xa3, 0x73, 0xc6, 0xb6, 0xc8, + 0xb0, 0xc8, 0xb4, 0xc7, 0xa8, 0xc8, 0xa7, 0xc6, 0x80, 0xc4, 0xb0, 0xc7, 0xaf, 0x6c, + 0xc8, 0xbb, 0xc4, 0x81, 0xc3, 0x93, 0xc7, 0x8c, 0xc7, 0xb4, 0xe1, 0x9b, 0x9c, 0xc4, + 0xa1, 0xc6, 0xa8, 0xc7, 0xbc, 0xc3, 0x9d, 0xc4, 0x8a, 0xc6, 0x82, 0xc6, 0x9c, 0xc7, + 0xb4, 0xc3, 0x83, 0xc8, 0xae, 0xc3, 0x93, 0xe1, 0x9a, 0xab, 0xc7, 0x8a, 0xc7, 0xb5, + 0xc2, 0xbc, 0xc4, 0x92, 0xc3, 0x9b, 0xc7, 0x8c, 0xc5, 0xa3, 0xc9, 0x84, 0xc4, 0xb5, + 0xc3, 0xba, 0xc6, 0xb3, 0x46, 0xc7, 0x8f, 0xe1, 0x9a, 0xab, 0xc8, 0x8d, 0xc7, 0xac, + 0x40, 0xc7, 0xbd, 0xc8, 0xa1, 0xc4, 0xa8, 0xc4, 0x86, 0xc3, 0xaa, 0xc4, 0xbc, 0xc6, + 0x80, 0x76, 0xc7, 0xb0, 0xc4, 0x85, 0xc5, 0xb7, 0x2a, 0xc4, 0xb7, 0xc2, 0xb6, 0xc8, + 0xa8, 0xc6, 0xa6, 0x6f, 0xc4, 0xad, 0xc8, 0x90, 0xc4, 0xb9, 0xc8, 0x9a, 0xc6, 0x95, + 0xc5, 0x80, 0xc3, 0xa5, 0xe1, 0x9b, 0x83, 0x5a, + ], + asset_base: [ + 0x6f, 0x2d, 0x95, 0xed, 0x1d, 0x96, 0x0b, 0x7a, 0xe1, 0xcf, 0x9c, 0x0b, 0x66, 0xe8, + 0x5a, 0xdd, 0x2c, 0xf1, 0xcd, 0x44, 0x6e, 0x02, 0x74, 0x51, 0x2e, 0x3b, 0x99, 0x6d, + 0x8e, 0xe7, 0x77, 0xa2, + ], + }, + TestVector { + key: [ + 0xd7, 0x5a, 0xf5, 0x78, 0x2a, 0x5c, 0x72, 0x16, 0x38, 0xf7, 0x59, 0x32, 0x91, 0x11, + 0x49, 0x93, 0x24, 0x05, 0x3a, 0x5d, 0x1e, 0x1b, 0x2a, 0x4a, 0xb3, 0xcd, 0xf7, 0xf8, + 0x24, 0x12, 0xff, 0x42, + ], + description: [ + 0xc3, 0xa1, 0xc7, 0xa6, 0xc4, 0xa7, 0xc5, 0xa9, 0x37, 0xc4, 0x87, 0xc7, 0xb0, 0xe1, + 0x9a, 0xa1, 0xe2, 0xb1, 0xa1, 0xc6, 0x83, 0xc3, 0xa9, 0xc6, 0xa9, 0xc8, 0x82, 0xe2, + 0xb1, 0xab, 0xc4, 0xa5, 0xe1, 0x9b, 0x99, 0xc6, 0x9e, 0xe1, 0x9a, 0xaa, 0xc8, 0xa0, + 0xc8, 0xa2, 0xc4, 0x93, 0xe1, 0x9b, 0x83, 0xe1, 0x9b, 0x92, 0xe1, 0x9b, 0x86, 0xc5, + 0xb5, 0xc2, 0xb4, 0xc5, 0x97, 0xc6, 0x87, 0xc4, 0x9a, 0xe1, 0x9b, 0x85, 0xc8, 0x91, + 0xe1, 0x9a, 0xa7, 0xc6, 0xa1, 0xc3, 0x81, 0xc6, 0xab, 0xc5, 0x93, 0xc6, 0xb6, 0xc7, + 0x86, 0x3f, 0xcd, 0xb5, 0xe2, 0xb1, 0xa5, 0xc7, 0x86, 0xc5, 0x88, 0xc2, 0xa5, 0xc3, + 0xa5, 0xce, 0x87, 0xc5, 0x8c, 0xc5, 0x9d, 0xe1, 0x9b, 0xa7, 0x70, 0xc3, 0x98, 0xc2, + 0xb7, 0xe1, 0x9b, 0xb0, 0xc4, 0x85, 0xc6, 0x82, 0xc3, 0x85, 0xc4, 0x9c, 0xe1, 0x9b, + 0x9d, 0x2c, 0xc4, 0xa6, 0xc9, 0x86, 0xe1, 0x9b, 0xab, 0xc3, 0xb6, 0xc7, 0xad, 0xc5, + 0xbb, 0xe1, 0x9a, 0xa4, 0x39, 0xc5, 0x82, 0xc6, 0x85, 0xc9, 0x82, 0x41, 0xcd, 0xbb, + 0xc3, 0x81, 0xc6, 0x8b, 0xe1, 0x9b, 0xb0, 0xc4, 0xa6, 0x49, 0x6a, 0xce, 0x89, 0xc8, + 0xbb, 0xc6, 0xa5, 0xc5, 0xa7, 0xc7, 0xa9, 0xe2, 0xb1, 0xb7, 0x3c, 0xc5, 0xb5, 0xc3, + 0xbb, 0xc7, 0xad, 0xc3, 0x84, 0xc3, 0xac, 0xe2, 0xb1, 0xbd, 0xc8, 0xaa, 0x51, 0xc2, + 0xaa, 0xcd, 0xba, 0xc5, 0xa1, 0x52, 0x62, 0xc6, 0x9f, 0xc4, 0xb6, 0xc8, 0x83, 0x6f, + 0xc3, 0x9f, 0x48, 0xc6, 0x8f, 0x31, 0xc3, 0x83, 0xe1, 0x9b, 0x80, 0xc5, 0x93, 0xcd, + 0xba, 0xc4, 0xb6, 0xc7, 0x9c, 0xe1, 0x9b, 0x82, 0xe2, 0xb1, 0xb1, 0x28, 0xc6, 0x94, + 0xc7, 0x83, 0xc5, 0x9d, 0xc7, 0x86, 0xe1, 0x9a, 0xbe, 0xc5, 0xa9, 0xc7, 0x83, 0xe2, + 0xb1, 0xad, 0xe1, 0x9b, 0x81, 0xc3, 0x96, 0x60, 0xc4, 0xa3, 0xc2, 0xb7, 0xc5, 0xb6, + 0xc5, 0x93, 0x74, 0xc6, 0x97, 0x21, 0xe2, 0xb1, 0xae, 0xc2, 0xa8, 0xcd, 0xb1, 0xc6, + 0x89, 0xc3, 0xbe, 0xe1, 0x9a, 0xb3, 0xc4, 0xa4, 0xc5, 0x94, 0xc8, 0xb8, 0xe1, 0x9b, + 0x8e, 0xc5, 0x84, 0xc2, 0xbc, 0xc3, 0x86, 0x55, 0xe1, 0x9b, 0x87, 0xce, 0x85, 0xe1, + 0x9a, 0xb9, 0xc8, 0x90, 0xe1, 0x9b, 0x8e, 0x72, 0xc7, 0x82, 0xc3, 0x85, 0xc4, 0x9f, + 0xcd, 0xb5, 0xe1, 0x9b, 0xa7, 0xc3, 0x88, 0x73, 0xc2, 0xa5, 0xc6, 0x88, 0xc4, 0xb4, + 0xc5, 0xa9, 0xcd, 0xbe, 0xc3, 0x99, 0xe1, 0x9a, 0xbf, 0xc4, 0xb0, 0xc4, 0xbf, 0xe2, + 0xb1, 0xb1, 0xc3, 0x8e, 0x2a, 0xc5, 0x93, 0xc8, 0xb6, 0xc6, 0x89, 0xc6, 0x8b, 0x5a, + 0x64, 0xe1, 0x9b, 0x9d, 0x41, 0xc3, 0xba, 0xcd, 0xbe, 0xc7, 0x90, 0xc8, 0x8b, 0xc6, + 0x82, 0xc6, 0xb0, 0xe1, 0x9a, 0xb7, 0xc4, 0xa9, 0xc4, 0x9d, 0xe2, 0xb1, 0xab, 0xc4, + 0x84, 0xc5, 0xb4, 0xc8, 0xb7, 0xc7, 0x81, 0xc4, 0xad, 0xce, 0x88, 0xc8, 0xb7, 0xc3, + 0xa8, 0xcd, 0xbc, 0xc6, 0x97, 0xe2, 0xb1, 0xa8, 0xc8, 0x84, 0xc8, 0xa2, 0xe1, 0x9a, + 0xaa, 0xc5, 0xa4, 0xc5, 0xb3, 0xc5, 0x88, 0x25, 0xc7, 0xb4, 0xc6, 0xa7, 0xc4, 0xbc, + 0x36, 0x3c, 0xc8, 0x8b, 0x6a, 0xc9, 0x84, 0xe1, 0x9b, 0x9e, 0xc7, 0xa9, 0xe1, 0x9b, + 0x89, 0xc5, 0xb1, 0xc7, 0xb6, 0xc8, 0x8a, 0xcd, 0xb5, 0xc4, 0x80, 0xe1, 0x9b, 0x98, + 0xc6, 0x94, 0xc6, 0x82, 0xc4, 0xb4, 0xe1, 0x9a, 0xa3, 0xe1, 0x9b, 0x8f, 0xc3, 0xb6, + 0xc5, 0xb3, 0xe1, 0x9b, 0x8a, 0xc8, 0xa2, 0xc7, 0x97, 0xc3, 0xb9, 0xc5, 0xac, 0xe1, + 0x9a, 0xbb, 0xe1, 0x9b, 0xa5, 0xc5, 0xb2, 0xc5, 0x8c, 0xe1, 0x9b, 0x85, 0xc5, 0x8c, + 0xc7, 0xab, 0xc7, 0xab, 0xe2, 0xb1, 0xbb, 0x48, + ], + asset_base: [ + 0x35, 0x3e, 0x4f, 0xa9, 0x48, 0x59, 0xab, 0x52, 0xfc, 0xc2, 0xdd, 0x1c, 0x91, 0x45, + 0x3c, 0x09, 0x3f, 0x15, 0x43, 0x31, 0x43, 0x65, 0x80, 0x38, 0xba, 0xc3, 0xaa, 0xf0, + 0x89, 0xf0, 0xd4, 0x23, + ], + }, + TestVector { + key: [ + 0x1b, 0x39, 0xca, 0x34, 0x32, 0x36, 0xdf, 0xab, 0x88, 0xfe, 0x78, 0x12, 0x10, 0xe1, + 0xe8, 0x79, 0x29, 0x3b, 0xe0, 0xf4, 0xc5, 0x1c, 0x86, 0xfd, 0x8a, 0x6f, 0xff, 0xdb, + 0xb4, 0xad, 0x26, 0x73, + ], + description: [ + 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xa5, 0xc2, 0xba, 0xc6, 0x8c, 0xc3, 0x81, 0xc6, 0x82, + 0xc4, 0x80, 0xc4, 0xa3, 0xc6, 0xad, 0xc3, 0x80, 0xc8, 0x8a, 0xc8, 0x99, 0xe2, 0xb1, + 0xae, 0xc5, 0xa2, 0xc8, 0x8e, 0xc3, 0xb4, 0xc6, 0x86, 0xc5, 0xa3, 0xc9, 0x88, 0xcd, + 0xb4, 0x25, 0xe2, 0xb1, 0xa4, 0x50, 0xc3, 0x88, 0xc4, 0xaf, 0xc8, 0x86, 0xc3, 0xa5, + 0xe1, 0x9b, 0x99, 0xc7, 0xb4, 0xc4, 0xb6, 0xc5, 0x99, 0xc5, 0x8b, 0xc8, 0x85, 0x21, + 0xe1, 0x9a, 0xaa, 0xc4, 0x95, 0xc3, 0xa9, 0xe1, 0x9a, 0xba, 0x5d, 0xc4, 0xa4, 0xc6, + 0x9b, 0x4e, 0x37, 0x35, 0xc2, 0xb2, 0xc7, 0x9b, 0xe1, 0x9a, 0xba, 0xc9, 0x80, 0xc7, + 0x9b, 0xc3, 0x9b, 0xc3, 0xb4, 0xe1, 0x9b, 0x9b, 0xc3, 0xb8, 0xc7, 0xbe, 0xc8, 0x9f, + 0xc8, 0xa0, 0xc7, 0x8a, 0xcd, 0xb3, 0xc2, 0xae, 0xc4, 0xaf, 0xc4, 0x84, 0x5b, 0xc8, + 0x87, 0xc9, 0x84, 0xc3, 0x87, 0xc8, 0xa9, 0xc3, 0xa5, 0xc4, 0x87, 0xc5, 0xbf, 0x37, + 0xc5, 0xac, 0xe1, 0x9a, 0xaa, 0xc6, 0x80, 0xe2, 0xb1, 0xa0, 0xc5, 0xb7, 0xc6, 0x8d, + 0xc3, 0xbb, 0xc7, 0x85, 0xc2, 0xb6, 0xc4, 0x90, 0xe1, 0x9a, 0xba, 0xc3, 0xb7, 0xe2, + 0xb1, 0xb6, 0xc6, 0xa8, 0xc7, 0xac, 0xc4, 0xaf, 0xce, 0x8a, 0xc6, 0x8f, 0xc2, 0xa1, + 0xc3, 0x82, 0xe1, 0x9b, 0x96, 0xc8, 0xb5, 0xc4, 0x9f, 0xc3, 0x88, 0xe1, 0x9b, 0xa6, + 0xc5, 0xb9, 0xc5, 0xad, 0xe1, 0x9a, 0xa2, 0xc3, 0x95, 0x5c, 0xe1, 0x9a, 0xb2, 0xcd, + 0xb2, 0xc8, 0xb3, 0xcd, 0xb7, 0x7b, 0xc5, 0xb6, 0xc8, 0xb0, 0x7a, 0xc7, 0x9e, 0x4a, + 0xc4, 0x86, 0xc3, 0xbf, 0xc7, 0xb2, 0xc8, 0xbc, 0xc9, 0x87, 0xc3, 0x8c, 0xe1, 0x9a, + 0xbb, 0xc8, 0x8d, 0xc3, 0x9a, 0xc9, 0x8e, 0xc5, 0xb3, 0xe2, 0xb1, 0xab, 0xc5, 0x89, + 0xc8, 0x9e, 0xe1, 0x9a, 0xb3, 0xc7, 0xb7, 0xc4, 0x8d, 0xe1, 0x9b, 0x84, 0xe1, 0x9b, + 0xa3, 0xc3, 0xbd, 0xc5, 0x80, 0xc5, 0xab, 0xc3, 0xa6, 0xc4, 0x90, 0xc7, 0x90, 0xe1, + 0x9b, 0x97, 0xc5, 0xbb, 0xc3, 0x80, 0xc5, 0x98, 0xc3, 0xa4, 0xe1, 0x9b, 0x9a, 0xc7, + 0x90, 0xc3, 0xb5, 0xc8, 0xaf, 0xc2, 0xac, 0xe1, 0x9b, 0x9f, 0xc5, 0x82, 0x34, 0xce, + 0x87, 0xc6, 0xa4, 0xc3, 0xa5, 0xc4, 0x89, 0x44, 0xc3, 0x8b, 0xc4, 0x84, 0xc7, 0xac, + 0xe1, 0x9b, 0xb0, 0xc5, 0x82, 0x76, 0xc8, 0x99, 0xc4, 0x9d, 0xc7, 0xad, 0xc3, 0xa3, + 0x31, 0xc3, 0xb2, 0xc5, 0x82, 0xc2, 0xbd, 0xc7, 0x8c, 0xc2, 0xb5, 0xe1, 0x9a, 0xaf, + 0xc7, 0x9a, 0xe1, 0x9a, 0xbb, 0xc5, 0xa9, 0xc6, 0x94, 0xc7, 0x82, 0xe2, 0xb1, 0xb5, + 0xc5, 0x9b, 0xe1, 0x9b, 0xa3, 0xc6, 0xb2, 0xc4, 0x88, 0x7d, 0xc4, 0x81, 0xc5, 0xb0, + 0xe1, 0x9a, 0xa4, 0xc8, 0xbb, 0xe2, 0xb1, 0xbe, 0xc4, 0x98, 0xc4, 0xba, 0xc8, 0x8d, + 0x68, 0xc4, 0x99, 0xc8, 0x86, 0x40, 0x59, 0xe1, 0x9a, 0xa1, 0xe1, 0x9b, 0x9a, 0xc7, + 0x89, 0xc8, 0x99, 0xc7, 0xa8, 0x4e, 0xc9, 0x81, 0xc5, 0x92, 0xc8, 0xb0, 0xcd, 0xb2, + 0xc7, 0xa4, 0xc8, 0x95, 0xe1, 0x9a, 0xb3, 0xc4, 0x88, 0x32, 0xc7, 0x88, 0xc2, 0xa7, + 0x34, 0x75, 0xc6, 0xb0, 0xc7, 0x9f, 0xc8, 0xb2, 0x50, 0xc5, 0x95, 0xc7, 0xb9, 0x50, + 0xc2, 0xa5, 0xc3, 0xa3, 0xc9, 0x84, 0xce, 0x85, 0xe1, 0x9b, 0xad, 0xc4, 0x9e, 0xe1, + 0x9b, 0xa3, 0xc5, 0x81, 0x5d, 0xc6, 0xb8, 0xe1, 0x9a, 0xb7, 0xc4, 0x99, 0xc2, 0xb2, + 0xc4, 0xa2, 0xc4, 0x99, 0xc6, 0x8f, 0x26, 0xc3, 0x88, 0xc4, 0xa3, 0xc5, 0x87, 0xc9, + 0x8f, 0x59, 0xc8, 0x85, 0xc7, 0x9a, 0xe1, 0x9b, 0x8a, 0xe2, 0xb1, 0xb7, 0xc8, 0x83, + 0xe1, 0x9b, 0x88, 0x61, 0xc6, 0xa9, 0xc4, 0xa2, + ], + asset_base: [ + 0x76, 0xe9, 0x3a, 0xa6, 0xa3, 0x60, 0x1a, 0x94, 0xdf, 0xde, 0x01, 0xd9, 0x8c, 0x63, + 0xc6, 0xf1, 0x28, 0x5b, 0x22, 0x28, 0x47, 0x16, 0x86, 0x05, 0x85, 0x93, 0x7c, 0x3d, + 0xaf, 0x60, 0x7b, 0xbc, + ], + }, + TestVector { + key: [ + 0x56, 0x6e, 0x78, 0x1a, 0xc9, 0x8e, 0x99, 0x13, 0x08, 0x98, 0x1b, 0x7c, 0xdc, 0x73, + 0x7c, 0x66, 0x78, 0x5b, 0xe5, 0x31, 0xe2, 0x0a, 0xef, 0x77, 0x7a, 0xac, 0xe0, 0x6d, + 0x38, 0xfa, 0x02, 0x6b, + ], + description: [ + 0xc6, 0xa4, 0xc7, 0xae, 0xe1, 0x9a, 0xa6, 0xc8, 0x91, 0xc2, 0xb5, 0xc8, 0xaa, 0xc3, + 0x81, 0x2a, 0xc4, 0x90, 0xc6, 0xa0, 0xe1, 0x9a, 0xb0, 0xc3, 0x85, 0xc8, 0x8b, 0xc6, + 0xaa, 0x4d, 0xc8, 0x94, 0xc7, 0x98, 0xc8, 0xa7, 0xc8, 0x9b, 0xc3, 0x8f, 0xe1, 0x9b, + 0x81, 0xc2, 0xab, 0xe2, 0xb1, 0xa5, 0xc6, 0xb2, 0xce, 0x84, 0x73, 0xc5, 0xb1, 0x63, + 0xc2, 0xb7, 0xc2, 0xb7, 0xc9, 0x87, 0xce, 0x8c, 0xc3, 0xb4, 0xc4, 0xba, 0xe1, 0x9b, + 0x9b, 0x48, 0xcd, 0xbe, 0x28, 0xe2, 0xb1, 0xbd, 0xe1, 0x9a, 0xa9, 0xc5, 0x9d, 0x61, + 0xc4, 0xbe, 0xc2, 0xbf, 0xc3, 0x9f, 0xc7, 0xa5, 0xc5, 0xb0, 0x67, 0xc7, 0x99, 0xe2, + 0xb1, 0xa7, 0xc5, 0xac, 0xc4, 0xbe, 0xc8, 0xa6, 0xe1, 0x9a, 0xaa, 0xc7, 0xb9, 0xc9, + 0x88, 0xc6, 0x9f, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xaa, 0xc3, 0x89, 0xc3, 0x83, 0xc7, + 0x87, 0xc2, 0xac, 0xc7, 0xa5, 0xe1, 0x9b, 0xae, 0xc4, 0xb0, 0xc3, 0xa6, 0xc6, 0x90, + 0xc7, 0xb2, 0xc3, 0xa7, 0xc2, 0xb8, 0xc5, 0x9a, 0xc5, 0xa1, 0xe1, 0x9b, 0x8c, 0xc5, + 0xac, 0xc8, 0xb7, 0xe2, 0xb1, 0xa8, 0xc3, 0xbc, 0xc9, 0x8e, 0x5e, 0xc2, 0xb4, 0xc7, + 0xb3, 0xc5, 0xba, 0xc8, 0xac, 0xc6, 0x92, 0x6c, 0x2a, 0xc4, 0x82, 0xc5, 0xac, 0xc5, + 0xaf, 0xc8, 0x99, 0xc8, 0xbd, 0xc2, 0xb3, 0xe1, 0x9a, 0xb4, 0x3f, 0xe1, 0x9a, 0xb5, + 0xcd, 0xb2, 0x6b, 0xc3, 0x98, 0xc3, 0xbd, 0xc3, 0x9c, 0xc2, 0xac, 0x3b, 0xc6, 0xa8, + 0xc3, 0x8c, 0x58, 0x2f, 0x5e, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0x95, 0xe1, 0x9b, 0xa1, + 0xe2, 0xb1, 0xba, 0xc7, 0xa4, 0xe2, 0xb1, 0xa0, 0xc4, 0x9d, 0xc3, 0xa4, 0xe1, 0x9b, + 0xa5, 0xe2, 0xb1, 0xab, 0xc6, 0x83, 0xc2, 0xa4, 0x4e, 0xc4, 0xb1, 0xe1, 0x9b, 0xa9, + 0xc8, 0xb1, 0xc5, 0x93, 0xe2, 0xb1, 0xae, 0xc7, 0x99, 0xc3, 0xbe, 0xe2, 0xb1, 0xa3, + 0x7a, 0x60, 0xc7, 0x94, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x80, 0xc8, 0xad, 0xc8, 0x93, + 0x48, 0xe1, 0x9b, 0x83, 0xc6, 0xab, 0xe1, 0x9a, 0xa2, 0xc4, 0xbe, 0xc3, 0x89, 0xc7, + 0xb7, 0xcd, 0xb5, 0xc6, 0x88, 0xe1, 0x9b, 0x85, 0x6a, 0x43, 0xc9, 0x84, 0xc7, 0x91, + 0x31, 0xc9, 0x8b, 0xe1, 0x9a, 0xa8, 0x6e, 0xc7, 0x96, 0xc3, 0x9c, 0x28, 0xc3, 0x90, + 0x41, 0xc5, 0x8b, 0xc5, 0x8d, 0xc2, 0xab, 0xcd, 0xb5, 0xc7, 0xb0, 0x5d, 0xc3, 0x8b, + 0xc8, 0xaa, 0xe2, 0xb1, 0xa6, 0xe2, 0xb1, 0xbf, 0xc6, 0xb7, 0xe1, 0x9a, 0xb8, 0xc5, + 0xbb, 0xe1, 0x9a, 0xaf, 0xe2, 0xb1, 0xb3, 0xc7, 0xa8, 0xc8, 0xb8, 0xc4, 0xb0, 0xe2, + 0xb1, 0xaf, 0xe1, 0x9b, 0xa9, 0xe1, 0x9b, 0x9f, 0xc3, 0x81, 0xc2, 0xaa, 0xc5, 0xae, + 0xc5, 0x83, 0x65, 0xc7, 0xbd, 0xc5, 0x9d, 0x2f, 0xc5, 0x91, 0xc6, 0xb6, 0xc2, 0xb9, + 0xc2, 0xa1, 0x4b, 0xc6, 0x9f, 0xc3, 0xb9, 0xcd, 0xb1, 0xe1, 0x9a, 0xbb, 0xc8, 0xad, + 0xc2, 0xa1, 0xc3, 0x9c, 0xc3, 0x8f, 0xc5, 0x8e, 0xc3, 0xb5, 0xc2, 0xb7, 0xc4, 0xa4, + 0xc5, 0xa5, 0xe1, 0x9b, 0x8b, 0xc4, 0xb2, 0xc2, 0xa2, 0xc7, 0x86, 0xc3, 0xb8, 0x4c, + 0xc3, 0x9b, 0xc5, 0x81, 0xc5, 0x95, 0xe1, 0x9b, 0x85, 0xc6, 0x94, 0xc4, 0xa6, 0xc4, + 0xac, 0x4f, 0xc3, 0xb0, 0xe1, 0x9b, 0xad, 0xc7, 0xa4, 0xc2, 0xa4, 0xc5, 0xa4, 0xe1, + 0x9a, 0xbb, 0xc4, 0xa4, 0xe1, 0x9a, 0xbf, 0xc3, 0xb6, 0xc6, 0xaf, 0xc6, 0xbb, 0xc8, + 0x94, 0xc3, 0xa6, 0xc3, 0xb4, 0xe1, 0x9b, 0x9c, 0xc3, 0x9b, 0xc7, 0xb3, 0xc5, 0xbc, + 0xce, 0x8a, 0xc7, 0xb2, 0xc3, 0xa9, 0x23, 0xc5, 0xa0, 0xc7, 0xba, 0xc2, 0xa1, 0xc9, + 0x85, 0xc6, 0xa9, 0xc7, 0xac, 0xc7, 0x9f, 0x5a, + ], + asset_base: [ + 0x50, 0xf6, 0x66, 0x1f, 0x02, 0x22, 0x48, 0x1e, 0x18, 0x94, 0x80, 0x9a, 0x17, 0xd0, + 0xaf, 0xeb, 0x5e, 0xf9, 0x74, 0x34, 0x43, 0x5d, 0x32, 0xa0, 0x4b, 0x3b, 0x16, 0xb2, + 0x45, 0xc8, 0xed, 0x0a, + ], + }, + TestVector { + key: [ + 0x86, 0xcc, 0x5e, 0x4f, 0xea, 0x9b, 0x7c, 0x1d, 0x0e, 0x1f, 0xa8, 0xb6, 0xa8, 0xf2, + 0x31, 0xb4, 0x56, 0x2e, 0x53, 0x89, 0xe9, 0xe7, 0x92, 0x16, 0x57, 0x67, 0x96, 0xce, + 0x3a, 0x49, 0x40, 0x6b, + ], + description: [ + 0xc2, 0xa1, 0xc4, 0x8e, 0xc3, 0x9f, 0xc5, 0xbb, 0x74, 0xc4, 0x82, 0xc5, 0xbb, 0x7d, + 0xc6, 0xae, 0xc8, 0xa9, 0xe2, 0xb1, 0xbf, 0xc7, 0x90, 0xc7, 0x93, 0xc9, 0x89, 0xc7, + 0xa5, 0xc6, 0x8b, 0xc7, 0xbd, 0xe2, 0xb1, 0xb9, 0xcd, 0xbd, 0x4c, 0xcd, 0xbe, 0xc5, + 0x8d, 0x4d, 0xc4, 0xb2, 0xe2, 0xb1, 0xa3, 0x31, 0xe1, 0x9a, 0xbe, 0xc8, 0xa1, 0xc4, + 0xab, 0x58, 0xc7, 0x89, 0xc4, 0xb3, 0x7d, 0xc9, 0x88, 0xc7, 0xbc, 0xc4, 0x8d, 0xc4, + 0xae, 0xc4, 0x98, 0xc7, 0xaa, 0xc3, 0xb4, 0xc5, 0xbe, 0xc6, 0x98, 0x2b, 0xc2, 0xb3, + 0xc7, 0xaa, 0xc6, 0x83, 0xc6, 0x92, 0xc6, 0xb8, 0xe1, 0x9b, 0xaf, 0xc4, 0x95, 0xc4, + 0xbc, 0xc8, 0xa5, 0xc3, 0xb9, 0xc3, 0xae, 0xc4, 0xa8, 0xc6, 0x82, 0xe1, 0x9a, 0xad, + 0xc3, 0xab, 0xc8, 0x88, 0xc4, 0x9c, 0xc5, 0xba, 0xce, 0x87, 0xc3, 0x8b, 0xc7, 0xaf, + 0xc8, 0xa6, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x9f, 0xc2, 0xb3, 0xc7, 0x9e, 0x73, 0xc5, + 0x8a, 0x5c, 0xc5, 0x90, 0xc5, 0xb7, 0xc6, 0x87, 0xc5, 0x9a, 0xc3, 0x86, 0x78, 0xe1, + 0x9b, 0x9c, 0xc7, 0xae, 0xc8, 0x94, 0xc9, 0x82, 0xc8, 0xb8, 0x69, 0xc8, 0xb3, 0xc5, + 0x92, 0xe1, 0x9a, 0xa7, 0xc6, 0xb1, 0xc3, 0x85, 0xc5, 0xa5, 0xc4, 0xab, 0xc7, 0x97, + 0xe1, 0x9a, 0xb2, 0xc7, 0xb7, 0xc8, 0xa9, 0xe1, 0x9b, 0x92, 0xc3, 0xb8, 0xce, 0x86, + 0xc5, 0xa1, 0x5d, 0xc4, 0xb9, 0xce, 0x88, 0xc6, 0xb1, 0xc7, 0xb2, 0xc6, 0x90, 0xc6, + 0xaf, 0xe1, 0x9a, 0xb5, 0xce, 0x8c, 0x25, 0x47, 0xc6, 0xb1, 0xc4, 0x92, 0xc8, 0xba, + 0xc6, 0x95, 0xc8, 0xa6, 0xe2, 0xb1, 0xb5, 0xc5, 0xb0, 0xe2, 0xb1, 0xb3, 0xc7, 0xa5, + 0xc5, 0x98, 0xc8, 0xbb, 0xc4, 0x9b, 0xc5, 0x83, 0xc4, 0x82, 0xe2, 0xb1, 0xbf, 0xc4, + 0x9b, 0xc6, 0xa8, 0xc8, 0x8e, 0xe1, 0x9b, 0x88, 0xc8, 0xba, 0x2d, 0x54, 0xe1, 0x9a, + 0xb1, 0xc2, 0xa9, 0xe1, 0x9b, 0x97, 0xc9, 0x8a, 0xc5, 0x8a, 0xc4, 0x80, 0xc8, 0xb1, + 0xc4, 0x9e, 0xc7, 0xac, 0xc3, 0x82, 0xc7, 0xb6, 0xc4, 0x8f, 0xc5, 0xa6, 0xc4, 0x98, + 0xe2, 0xb1, 0xa4, 0x3f, 0xcd, 0xb5, 0xc4, 0xa8, 0xc8, 0xa7, 0xe1, 0x9a, 0xb9, 0xc8, + 0xad, 0xe1, 0x9b, 0xaa, 0xc4, 0x97, 0xc7, 0xb9, 0x3d, 0xc6, 0xb9, 0xc8, 0x86, 0xc5, + 0x9d, 0xc2, 0xa4, 0xc7, 0xba, 0xc6, 0xb1, 0xc7, 0xbb, 0xe1, 0x9a, 0xa8, 0xc7, 0x99, + 0xc6, 0x93, 0x71, 0x5c, 0xc3, 0x91, 0xc8, 0x82, 0xc3, 0x9c, 0x3c, 0xc2, 0xa1, 0xe2, + 0xb1, 0xba, 0x5b, 0xc5, 0x9a, 0xc6, 0xba, 0x54, 0xce, 0x88, 0xe1, 0x9a, 0xad, 0x6a, + 0xc7, 0xb5, 0xe2, 0xb1, 0xbf, 0xc4, 0xbd, 0x39, 0xc9, 0x8b, 0xc8, 0x8e, 0x76, 0x49, + 0xc6, 0xb2, 0xc7, 0xbc, 0x31, 0xc7, 0xa8, 0xc9, 0x88, 0xc4, 0xab, 0xc5, 0x90, 0xc3, + 0x9f, 0xc3, 0x91, 0xe1, 0x9a, 0xbf, 0xe1, 0x9b, 0xab, 0xc5, 0xab, 0xe2, 0xb1, 0xbe, + 0xe2, 0xb1, 0xa6, 0xc9, 0x86, 0xc5, 0x97, 0xe1, 0x9a, 0xa1, 0x63, 0xc7, 0x9c, 0xc8, + 0xab, 0xe1, 0x9a, 0xaa, 0x3a, 0xc6, 0x8b, 0xc3, 0x82, 0xe2, 0xb1, 0xa7, 0xe1, 0x9b, + 0x9d, 0xc2, 0xb2, 0xe1, 0x9b, 0x98, 0x4c, 0xce, 0x85, 0xc5, 0xbb, 0x6c, 0xc4, 0xb5, + 0xc3, 0xb6, 0xc2, 0xa3, 0xc8, 0xb2, 0xc8, 0x8f, 0xc5, 0x8a, 0x3f, 0x74, 0xc7, 0x8c, + 0x63, 0xe1, 0x9a, 0xa6, 0xc3, 0x98, 0xc8, 0xb9, 0xc7, 0x9b, 0x45, 0xc6, 0x9a, 0xc7, + 0xb1, 0xc2, 0xba, 0x6c, 0x62, 0x66, 0xe1, 0x9a, 0xb7, 0xe1, 0x9b, 0xa3, 0xe1, 0x9b, + 0x8c, 0xe1, 0x9b, 0x80, 0xc2, 0xb0, 0xc8, 0xaa, 0xc5, 0xbc, 0xc5, 0xb0, 0xc4, 0xa0, + 0xcd, 0xb4, 0xc7, 0x9a, 0x3f, 0xc4, 0x85, 0x5a, + ], + asset_base: [ + 0xc9, 0x01, 0x55, 0x24, 0x71, 0x2e, 0x93, 0xf3, 0x40, 0x41, 0x31, 0x02, 0xda, 0x68, + 0xaf, 0xb4, 0xf5, 0x5f, 0xa2, 0x94, 0x4a, 0xc4, 0xc8, 0x32, 0x34, 0xb5, 0x8a, 0x1d, + 0x7a, 0x9c, 0xb6, 0x95, + ], + }, + TestVector { + key: [ + 0x43, 0x39, 0xfd, 0x2a, 0x6c, 0x66, 0x30, 0x2e, 0x31, 0x8e, 0x18, 0x41, 0xf7, 0xe6, + 0x36, 0xb7, 0x76, 0x58, 0xda, 0xfc, 0x9c, 0x8e, 0x96, 0x45, 0xc9, 0x46, 0xe9, 0x5e, + 0x56, 0x9c, 0x3c, 0x45, + ], + description: [ + 0xc9, 0x80, 0xc4, 0x80, 0xe1, 0x9a, 0xb0, 0xc4, 0xa3, 0xc6, 0x8e, 0xc5, 0xb2, 0xc6, + 0x8e, 0x3f, 0xc8, 0xb7, 0xc6, 0xb4, 0xc6, 0xb5, 0x65, 0xc7, 0xa5, 0xc8, 0x9e, 0xc6, + 0x97, 0xc3, 0xb1, 0xc6, 0x9c, 0xcd, 0xbd, 0x29, 0xc9, 0x88, 0xc2, 0xa2, 0xce, 0x86, + 0xc3, 0xb8, 0xc6, 0x9f, 0x3e, 0xc8, 0x81, 0xc3, 0x99, 0xc3, 0x88, 0xc7, 0xa2, 0xc5, + 0xb5, 0xc5, 0xb0, 0xc6, 0xa2, 0xc8, 0x89, 0xc6, 0x8c, 0xe1, 0x9b, 0xae, 0xc7, 0x83, + 0xcd, 0xba, 0xcd, 0xb5, 0xc3, 0xbc, 0xe1, 0x9b, 0xab, 0xc5, 0x8e, 0xc7, 0xb3, 0xc7, + 0xa7, 0xc4, 0xb5, 0xc3, 0x8b, 0xc3, 0xbf, 0x5e, 0xe1, 0x9a, 0xa0, 0xc6, 0xbe, 0xc8, + 0xb5, 0x31, 0xe2, 0xb1, 0xbe, 0xc7, 0x90, 0x7a, 0xc6, 0x81, 0x2a, 0xc7, 0xb7, 0xc3, + 0xbc, 0xc2, 0xb4, 0xc8, 0xa4, 0xc6, 0xa8, 0x64, 0xc7, 0x99, 0xc4, 0xa4, 0xc2, 0xbb, + 0xcd, 0xb1, 0xc6, 0xb0, 0xe1, 0x9b, 0xad, 0xc6, 0x95, 0x43, 0xc8, 0xb9, 0xc5, 0x98, + 0xc7, 0xb6, 0xc7, 0x9d, 0xc4, 0x8d, 0xc3, 0x90, 0x6c, 0xc7, 0x98, 0xc9, 0x80, 0xc2, + 0xae, 0xc6, 0x80, 0xc8, 0xba, 0xcd, 0xba, 0xc7, 0xa7, 0x41, 0xc6, 0xbf, 0xc4, 0x96, + 0xc7, 0x84, 0xc3, 0xa7, 0xc9, 0x89, 0xc8, 0xa2, 0xc8, 0x92, 0x71, 0xc2, 0xb5, 0xc4, + 0x9c, 0xc3, 0xbc, 0xc3, 0x84, 0xe1, 0x9b, 0xa4, 0x3b, 0xc7, 0x9d, 0xc4, 0xb9, 0xc4, + 0x9a, 0xc5, 0x93, 0xe1, 0x9a, 0xbb, 0xc8, 0x96, 0xc7, 0xa9, 0xc6, 0x8d, 0xc8, 0xb7, + 0x72, 0xc5, 0x8d, 0xc5, 0x83, 0xc4, 0x80, 0xc2, 0xb3, 0xc3, 0xb2, 0xc7, 0xa1, 0xc8, + 0x9c, 0xc3, 0x9c, 0xc6, 0x8a, 0xc3, 0xa2, 0xe1, 0x9b, 0x93, 0xc5, 0xa1, 0xc2, 0xa1, + 0xe1, 0x9b, 0x9a, 0xc3, 0xa5, 0xc3, 0x97, 0xc7, 0x82, 0xc2, 0xb4, 0xc3, 0x89, 0xc3, + 0xb3, 0xc9, 0x83, 0x70, 0xc7, 0xb8, 0xc5, 0xa4, 0xc8, 0x83, 0xc4, 0xb5, 0xc8, 0x84, + 0xc8, 0xa3, 0xe1, 0x9b, 0x86, 0xc7, 0x8c, 0xe2, 0xb1, 0xb5, 0x68, 0x5e, 0xc3, 0x8f, + 0xe2, 0xb1, 0xa6, 0xc6, 0xa1, 0xc8, 0xb9, 0xc4, 0x92, 0xc9, 0x8a, 0xc3, 0x8c, 0xe1, + 0x9b, 0x83, 0xe1, 0x9b, 0xa3, 0x4b, 0x59, 0xc8, 0xb9, 0xc6, 0xa6, 0xc8, 0x8d, 0xc6, + 0x8f, 0xe2, 0xb1, 0xba, 0xc5, 0xa4, 0xc8, 0xa7, 0xc5, 0xad, 0xc3, 0x95, 0xe1, 0x9a, + 0xb5, 0xc5, 0xa4, 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0xad, 0xc3, 0x92, 0xcd, 0xbe, 0xc6, + 0xa8, 0xc6, 0x83, 0xc4, 0x80, 0xe1, 0x9b, 0x84, 0xc3, 0xbc, 0xc5, 0x88, 0xe1, 0x9b, + 0x89, 0xc7, 0xb0, 0xc2, 0xba, 0xc3, 0x9f, 0xc9, 0x8e, 0xc3, 0x98, 0xc8, 0xbd, 0xc5, + 0x99, 0xc8, 0x90, 0xc2, 0xae, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x8d, 0xc6, 0xb8, 0xc2, + 0xb0, 0xe1, 0x9b, 0xa9, 0xc7, 0x89, 0xc9, 0x8d, 0xc8, 0xaf, 0xc5, 0xa4, 0xc4, 0x9f, + 0xc4, 0x98, 0xc7, 0x84, 0xc8, 0x99, 0xc3, 0x86, 0xc5, 0xa8, 0xe1, 0x9b, 0x94, 0x7e, + 0xc8, 0xa2, 0xc8, 0x9b, 0xc3, 0xa1, 0xce, 0x89, 0xe2, 0xb1, 0xa6, 0x51, 0xc4, 0x88, + 0xc2, 0xa2, 0xe1, 0x9a, 0xb3, 0xe2, 0xb1, 0xb9, 0xe2, 0xb1, 0xa6, 0x41, 0xe2, 0xb1, + 0xbc, 0xc5, 0xa3, 0xc3, 0x9c, 0xc8, 0x95, 0xc5, 0xab, 0xc3, 0xb4, 0x42, 0xc6, 0xb3, + 0xe1, 0x9b, 0x96, 0xe1, 0x9b, 0x98, 0xe1, 0x9b, 0xa7, 0xc6, 0x92, 0xc4, 0xa1, 0xe1, + 0x9b, 0xac, 0xc8, 0xb0, 0xc6, 0x91, 0xc7, 0x8f, 0x25, 0xc9, 0x86, 0xc6, 0x83, 0xc3, + 0xb4, 0xc5, 0xb5, 0xc5, 0x9f, 0xe1, 0x9b, 0x8a, 0xc6, 0x9d, 0xc8, 0x8a, 0xe1, 0x9b, + 0xa3, 0xe1, 0x9b, 0xa6, 0xe1, 0x9a, 0xb8, 0xe2, 0xb1, 0xa1, 0xc4, 0x9a, 0xc6, 0x86, + 0xc3, 0xa7, 0x5c, 0xe1, 0x9b, 0x97, 0x47, 0x5a, + ], + asset_base: [ + 0x13, 0x42, 0x79, 0x82, 0x9b, 0x56, 0xe2, 0xb0, 0x4a, 0xa0, 0xfb, 0x95, 0xf7, 0xfc, + 0x73, 0x79, 0x67, 0x24, 0x5d, 0x49, 0x6a, 0x6d, 0xfa, 0xa0, 0x28, 0x35, 0x2c, 0x39, + 0x2a, 0x58, 0x0d, 0x22, + ], + }, + TestVector { + key: [ + 0x46, 0x2e, 0xe2, 0x38, 0x00, 0xc2, 0x1e, 0x2b, 0xbd, 0x90, 0x2b, 0xf7, 0x2f, 0x60, + 0xe1, 0xab, 0x08, 0x26, 0xd3, 0x68, 0x0c, 0x6f, 0xd0, 0xa2, 0x6f, 0x87, 0xdb, 0xac, + 0xd0, 0xd7, 0x6c, 0xa0, + ], + description: [ + 0xc6, 0x96, 0x5e, 0x38, 0xc5, 0xa9, 0x73, 0x21, 0xc9, 0x88, 0xcd, 0xb7, 0xc3, 0xba, + 0xc5, 0x83, 0xc5, 0x99, 0xc8, 0x80, 0xc6, 0xbb, 0xe1, 0x9a, 0xb3, 0xc5, 0x98, 0xe1, + 0x9a, 0xa1, 0x72, 0xe1, 0x9b, 0x83, 0xc7, 0xa7, 0xc8, 0xbb, 0xc7, 0x95, 0xc6, 0xa7, + 0xc7, 0x9b, 0xc4, 0xbf, 0xc7, 0x97, 0xc3, 0xb1, 0xc3, 0x84, 0xe2, 0xb1, 0xa4, 0xc9, + 0x83, 0xc4, 0x96, 0xe2, 0xb1, 0xae, 0xc5, 0xb3, 0xc4, 0x82, 0xc8, 0xbd, 0xe1, 0x9b, + 0x95, 0xc6, 0x92, 0xe1, 0x9a, 0xa8, 0xc3, 0xb2, 0x25, 0xe1, 0x9b, 0x96, 0xc7, 0x90, + 0xc9, 0x80, 0xc3, 0x93, 0xc4, 0xa4, 0xc7, 0xb1, 0xc7, 0x82, 0xc4, 0x9b, 0xc9, 0x80, + 0xc5, 0x8c, 0xe1, 0x9b, 0xa7, 0x48, 0xc4, 0xb7, 0xcd, 0xb6, 0xc9, 0x8d, 0xc8, 0x9f, + 0xc9, 0x8d, 0xc5, 0xb5, 0xc8, 0x95, 0x79, 0xc4, 0xb6, 0xc5, 0xbb, 0xc4, 0x96, 0xe1, + 0x9a, 0xbb, 0xc3, 0xb1, 0xc3, 0xbb, 0x64, 0xc4, 0xbb, 0xc7, 0x84, 0xc8, 0x82, 0xe1, + 0x9a, 0xa4, 0x33, 0xcd, 0xb4, 0xc7, 0x8b, 0xc6, 0xaa, 0xc8, 0xba, 0xc3, 0xb4, 0xe2, + 0xb1, 0xbb, 0xe1, 0x9a, 0xb7, 0xc5, 0x89, 0x7a, 0xc2, 0xaa, 0xc8, 0x97, 0xc4, 0x9c, + 0xc4, 0xab, 0xc6, 0xb1, 0xc3, 0x9d, 0xc3, 0x95, 0xc3, 0xbf, 0xe2, 0xb1, 0xbf, 0xce, + 0x8c, 0x7a, 0xc8, 0xab, 0xc5, 0xa1, 0xc5, 0xa4, 0xc5, 0xb4, 0x24, 0xe2, 0xb1, 0xbf, + 0xc5, 0xb9, 0xe1, 0x9a, 0xb3, 0x60, 0xc5, 0xb8, 0x45, 0xc9, 0x83, 0x74, 0xc7, 0x86, + 0xc2, 0xbe, 0xc5, 0xb9, 0xc7, 0xab, 0xc7, 0x86, 0xc4, 0x84, 0xc5, 0x9b, 0xc6, 0x91, + 0xc4, 0x93, 0xc3, 0x93, 0xc5, 0xa6, 0xc8, 0x93, 0xc7, 0xbd, 0xc2, 0xb3, 0xcd, 0xba, + 0xc3, 0xb9, 0xc2, 0xb8, 0xc3, 0x87, 0xc8, 0xa1, 0xc6, 0x83, 0xc5, 0xbd, 0xe1, 0x9a, + 0xa7, 0xc8, 0x92, 0x43, 0xe1, 0x9b, 0x80, 0xc3, 0xb5, 0xc7, 0x8f, 0x74, 0x5a, 0xc6, + 0x94, 0xc5, 0x80, 0xc9, 0x81, 0xc4, 0xbe, 0xc6, 0xb3, 0xc2, 0xa8, 0xc7, 0xb7, 0xc6, + 0xb9, 0xc3, 0x97, 0xc6, 0xb7, 0xc6, 0xb4, 0xc6, 0x80, 0xc2, 0xb7, 0xc8, 0xa3, 0xcd, + 0xb1, 0xc7, 0xb4, 0xc7, 0xb0, 0xc7, 0xb2, 0xc7, 0x9f, 0xc2, 0xa2, 0xc3, 0xa6, 0xe2, + 0xb1, 0xa1, 0xe2, 0xb1, 0xb3, 0xe1, 0x9b, 0xa6, 0xcd, 0xbd, 0xe1, 0x9b, 0x88, 0xc6, + 0xb1, 0xc3, 0xaf, 0x42, 0x6f, 0xe1, 0x9b, 0xa2, 0xe2, 0xb1, 0xa7, 0xc5, 0x86, 0x6c, + 0xc3, 0x9b, 0xc2, 0xbc, 0xc8, 0x8f, 0xc2, 0xa9, 0xc8, 0xbd, 0xe2, 0xb1, 0xbc, 0xe2, + 0xb1, 0xb5, 0xe1, 0x9b, 0x83, 0x37, 0x37, 0xe2, 0xb1, 0xa0, 0xcd, 0xb5, 0xc7, 0xb7, + 0x64, 0xc7, 0xbb, 0xc7, 0xa5, 0xe1, 0x9a, 0xb7, 0xc3, 0xb4, 0xc7, 0x95, 0xc2, 0xb5, + 0xe1, 0x9b, 0x82, 0xc9, 0x81, 0xc4, 0xb6, 0xc7, 0xae, 0x26, 0xc4, 0xb6, 0x3e, 0xc3, + 0xba, 0xc3, 0xb7, 0xc7, 0x89, 0xc8, 0x87, 0xc7, 0x9d, 0xc5, 0xa5, 0xe2, 0xb1, 0xa8, + 0xc3, 0x96, 0xcd, 0xb7, 0x75, 0xe2, 0xb1, 0xa0, 0xc7, 0xa6, 0xc7, 0x83, 0x30, 0xc7, + 0xb8, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0x9a, 0xc3, 0xb8, 0xe2, 0xb1, 0xa3, 0x26, 0xc6, + 0x8a, 0xc6, 0x90, 0xc3, 0x8f, 0xe2, 0xb1, 0xa2, 0xc4, 0x88, 0xc2, 0xb3, 0xc9, 0x82, + 0x79, 0xc7, 0x8a, 0xc4, 0xb3, 0x78, 0xc5, 0xb6, 0xc3, 0x9c, 0x36, 0xc4, 0xa7, 0xc3, + 0xab, 0xc6, 0x87, 0xc5, 0xb4, 0xc6, 0xa2, 0xc7, 0x97, 0xc5, 0x96, 0xc9, 0x8c, 0x2b, + 0xc6, 0x80, 0xc7, 0x99, 0xc8, 0xb7, 0xc7, 0xb9, 0xc3, 0xa1, 0xc7, 0x8e, 0x7a, 0xc8, + 0x91, 0xe1, 0x9a, 0xb2, 0xe1, 0x9a, 0xae, 0x5f, 0xe1, 0x9b, 0x9b, 0xc6, 0x93, 0x3f, + 0xc3, 0xbd, 0xc3, 0xb2, 0xc8, 0x9a, 0xc8, 0x9f, + ], + asset_base: [ + 0xe4, 0xb5, 0xf3, 0x96, 0x78, 0x10, 0xbc, 0x94, 0xfe, 0x85, 0x44, 0x13, 0x38, 0x48, + 0xab, 0x35, 0xf6, 0xa5, 0x22, 0x2b, 0x0e, 0x74, 0xa8, 0xd3, 0xf0, 0x35, 0xdb, 0xdc, + 0x31, 0xa6, 0x3d, 0x04, + ], + }, + TestVector { + key: [ + 0x9e, 0x94, 0xc3, 0xbb, 0x8a, 0xb5, 0x31, 0x98, 0xd3, 0x9e, 0xf1, 0xb4, 0x05, 0xd1, + 0x75, 0x39, 0x20, 0x6f, 0x1b, 0x9f, 0x8e, 0xe9, 0xbc, 0x62, 0x58, 0xb5, 0xfe, 0xf5, + 0xb3, 0x0a, 0xb9, 0x4d, + ], + description: [ + 0x76, 0xe1, 0x9b, 0xa3, 0xc5, 0x8f, 0xc3, 0x95, 0xc6, 0xa6, 0x65, 0xc3, 0x9f, 0xc7, + 0xb0, 0xc6, 0x9c, 0xc4, 0x9d, 0xc5, 0xb8, 0xc6, 0x9c, 0x71, 0xe1, 0x9a, 0xbe, 0xc3, + 0xb4, 0xc8, 0xa4, 0xe1, 0x9b, 0xb0, 0x25, 0xc4, 0xaa, 0xc3, 0x9a, 0xe1, 0x9b, 0x8c, + 0xc8, 0x9e, 0x59, 0xe1, 0x9a, 0xb1, 0xc6, 0x91, 0xc2, 0xa2, 0x6b, 0xc7, 0xac, 0xc8, + 0xad, 0x77, 0xc7, 0xa4, 0xc5, 0xa2, 0xc6, 0x9d, 0xc3, 0x92, 0x29, 0x38, 0xc3, 0x9a, + 0xc9, 0x86, 0xc4, 0xac, 0xc2, 0xa4, 0xc3, 0x9b, 0xc6, 0xa4, 0x29, 0xce, 0x86, 0xc6, + 0xab, 0xe1, 0x9b, 0xa8, 0xe1, 0x9a, 0xb5, 0xc3, 0xa9, 0xc6, 0x84, 0xe1, 0x9a, 0xb1, + 0xc3, 0xb7, 0xe2, 0xb1, 0xbd, 0xc8, 0xb6, 0xc7, 0x9d, 0xc8, 0xa8, 0xc6, 0xa4, 0xe1, + 0x9a, 0xae, 0xe2, 0xb1, 0xad, 0xc5, 0xac, 0xc4, 0x99, 0xe1, 0x9a, 0xb1, 0xc9, 0x8c, + 0xc6, 0x85, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0xa6, 0xc4, 0xba, 0xcd, 0xbe, 0xe1, 0x9b, + 0x80, 0xe1, 0x9b, 0x9c, 0xc6, 0xb3, 0xc8, 0x84, 0xc5, 0x95, 0xc3, 0xae, 0xc9, 0x8a, + 0xc5, 0xbc, 0xc4, 0xbd, 0xc6, 0xbe, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xb1, 0x51, 0xc8, + 0x93, 0xc3, 0x8e, 0xc6, 0x83, 0xc5, 0xbb, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x8a, 0xc5, + 0xb1, 0x6a, 0xe1, 0x9a, 0xad, 0xc7, 0xbc, 0xc4, 0x86, 0xc8, 0x82, 0xe1, 0x9b, 0x9a, + 0xc8, 0x86, 0x53, 0xce, 0x89, 0xc3, 0x87, 0xc4, 0xb9, 0xc6, 0x85, 0xc8, 0xa0, 0x28, + 0xe2, 0xb1, 0xae, 0x62, 0xc8, 0x8b, 0xc4, 0xa2, 0xc5, 0x88, 0xc7, 0x8b, 0xc6, 0x99, + 0x62, 0xce, 0x85, 0xc5, 0x8c, 0xcd, 0xb0, 0xc2, 0xbf, 0xc7, 0xae, 0x29, 0xe1, 0x9a, + 0xb6, 0xc2, 0xb0, 0xc9, 0x8e, 0xc9, 0x88, 0xc7, 0x86, 0x55, 0x7b, 0xc3, 0x93, 0xc3, + 0xa2, 0xc5, 0x9e, 0xe1, 0x9b, 0xa2, 0x40, 0xe1, 0x9b, 0xad, 0xc8, 0x85, 0xc5, 0x8a, + 0xc5, 0x80, 0xc4, 0x9b, 0xc3, 0x8f, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x8a, 0x55, 0x4a, + 0x35, 0xc5, 0xa1, 0xc6, 0x94, 0xc7, 0x96, 0xc7, 0xa8, 0xc5, 0xaf, 0xc7, 0xbc, 0xc8, + 0xa7, 0xc8, 0x88, 0xc3, 0x8a, 0xc6, 0x84, 0xc7, 0xb6, 0x4b, 0xc6, 0x94, 0xe2, 0xb1, + 0xa6, 0xc2, 0xaa, 0xc7, 0xb2, 0xc8, 0xae, 0xc8, 0x97, 0xe2, 0xb1, 0xa5, 0xc3, 0xab, + 0xc4, 0xa4, 0xe1, 0x9a, 0xa3, 0xc4, 0x81, 0xc3, 0x8d, 0xcd, 0xbd, 0xc5, 0x91, 0xc3, + 0xb6, 0xe2, 0xb1, 0xa0, 0xc7, 0xa6, 0xc4, 0xb1, 0x23, 0xc7, 0xb1, 0xe1, 0x9b, 0x94, + 0xc5, 0xbc, 0xc6, 0x99, 0xc3, 0x87, 0xc6, 0x97, 0xc7, 0xb4, 0xc4, 0xb5, 0xc7, 0x9b, + 0x6b, 0xc5, 0x9c, 0xc4, 0x99, 0xc7, 0xba, 0x58, 0xe1, 0x9b, 0x88, 0xc7, 0xa1, 0xc6, + 0x90, 0xe1, 0x9b, 0x96, 0xe1, 0x9b, 0xaf, 0xc8, 0xba, 0xe1, 0x9a, 0xa4, 0x55, 0xc4, + 0x9c, 0xc7, 0xbe, 0xc4, 0x90, 0xc4, 0x80, 0xc2, 0xb5, 0xc7, 0x90, 0xce, 0x87, 0xc8, + 0x93, 0xc4, 0x9b, 0xcd, 0xb7, 0xc9, 0x8b, 0xc4, 0xbd, 0xe2, 0xb1, 0xbb, 0xc4, 0x8c, + 0xc3, 0x9f, 0xe1, 0x9a, 0xb3, 0xc4, 0x83, 0xc4, 0x98, 0xc7, 0x83, 0xe1, 0x9b, 0x9d, + 0xc3, 0x84, 0xe2, 0xb1, 0xbd, 0xc8, 0xbd, 0xc4, 0x82, 0xe1, 0x9b, 0xa7, 0xc5, 0x98, + 0xc3, 0xb0, 0xc5, 0x97, 0xc5, 0x94, 0xc7, 0xab, 0xce, 0x89, 0xc6, 0xb8, 0xc7, 0x86, + 0xc4, 0x94, 0xc4, 0x96, 0xc4, 0x81, 0x53, 0xcd, 0xbd, 0xc6, 0x86, 0xe1, 0x9b, 0x8e, + 0xc7, 0xb4, 0x3c, 0xe1, 0x9a, 0xa6, 0xc5, 0x9a, 0xe1, 0x9b, 0x96, 0xc8, 0xae, 0xe2, + 0xb1, 0xa9, 0xc7, 0xa2, 0xc5, 0x85, 0xc4, 0x97, 0xc4, 0x9c, 0xe1, 0x9a, 0xa1, 0xcd, + 0xbc, 0xc6, 0xaf, 0xc2, 0xac, 0xc9, 0x89, 0x5a, + ], + asset_base: [ + 0x3f, 0xc0, 0xbc, 0x12, 0x07, 0x8b, 0xf1, 0xf2, 0x24, 0x09, 0x2d, 0xb5, 0x81, 0x0b, + 0x00, 0xaf, 0x8a, 0xe0, 0xb6, 0xe6, 0x35, 0x50, 0xcf, 0xdc, 0xf6, 0xd6, 0x01, 0x0f, + 0x73, 0xab, 0xb0, 0x3c, + ], + }, + TestVector { + key: [ + 0xb2, 0xa8, 0xb7, 0x91, 0x5b, 0x37, 0x72, 0x5a, 0xd1, 0xcf, 0x5d, 0xc6, 0xeb, 0x4c, + 0xd0, 0x9a, 0xf4, 0xe1, 0x87, 0xf8, 0xcf, 0x27, 0x37, 0xed, 0x33, 0x7c, 0x77, 0x6e, + 0x93, 0xe2, 0xa0, 0x89, + ], + description: [ + 0xe1, 0x9a, 0xa7, 0x70, 0xc6, 0xa8, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0xa2, 0xc5, 0xad, + 0x7b, 0xe2, 0xb1, 0xa0, 0xc6, 0xa6, 0xc7, 0x98, 0xc7, 0xaf, 0x36, 0x44, 0xc2, 0xb0, + 0xc8, 0x8d, 0xc4, 0xac, 0xc6, 0xab, 0x7a, 0xc9, 0x83, 0xc6, 0x97, 0xe1, 0x9b, 0xa4, + 0xe1, 0x9a, 0xa1, 0xc7, 0xb3, 0xc4, 0x92, 0xc8, 0x8f, 0xc3, 0xb4, 0xc4, 0xa6, 0xc8, + 0x82, 0xc7, 0xa7, 0xe1, 0x9a, 0xb6, 0xe2, 0xb1, 0xae, 0xc4, 0x8f, 0xe1, 0x9a, 0xa2, + 0xc7, 0xb6, 0xc5, 0xb7, 0xc5, 0xa2, 0xe2, 0xb1, 0xa2, 0xc4, 0xa7, 0xc7, 0xaa, 0xc8, + 0xa9, 0xe2, 0xb1, 0xa6, 0xc3, 0x99, 0xc6, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x8f, 0xc8, + 0xa8, 0xc7, 0x9c, 0xe1, 0x9b, 0xae, 0xc2, 0xaa, 0xc6, 0xbe, 0xc3, 0x94, 0xc5, 0x94, + 0xc3, 0x9f, 0xc6, 0xa2, 0x69, 0xe1, 0x9a, 0xab, 0xc7, 0x9d, 0xc3, 0xad, 0xc7, 0xaf, + 0xcd, 0xb5, 0xc7, 0xba, 0xc8, 0xa3, 0xc5, 0xa6, 0xe1, 0x9b, 0xae, 0xc3, 0xa5, 0xc6, + 0x8e, 0xce, 0x86, 0xc4, 0x98, 0xc5, 0xa3, 0x32, 0x39, 0xc7, 0x9e, 0xc7, 0xae, 0xe1, + 0x9a, 0xa7, 0xc3, 0x91, 0xc8, 0x84, 0xc3, 0xa0, 0xc5, 0xaf, 0x2c, 0x54, 0x4b, 0xc6, + 0x81, 0xc3, 0x81, 0x2a, 0xcd, 0xb7, 0xe2, 0xb1, 0xa8, 0x5e, 0x4a, 0xe2, 0xb1, 0xa5, + 0x2b, 0xc3, 0xa0, 0xc3, 0xb8, 0xc8, 0x91, 0xc7, 0x80, 0xc4, 0xb2, 0x66, 0x3f, 0xc4, + 0x8b, 0xc5, 0x8d, 0xc9, 0x85, 0x39, 0xc3, 0x87, 0xc4, 0x8d, 0xc2, 0xb9, 0xc3, 0xaf, + 0x45, 0xc7, 0x89, 0xc4, 0xaa, 0xc4, 0x94, 0xc4, 0x96, 0xce, 0x85, 0xe2, 0xb1, 0xb7, + 0xc4, 0xbf, 0xc6, 0x9b, 0xc4, 0xae, 0x23, 0xcd, 0xb1, 0xc2, 0xbc, 0xe1, 0x9b, 0x80, + 0xc5, 0x88, 0xc6, 0x88, 0xc4, 0xb2, 0xc7, 0xae, 0x5b, 0xc6, 0x8f, 0xc7, 0xab, 0xc5, + 0xb3, 0xe1, 0x9b, 0x83, 0xc3, 0xad, 0xc5, 0xad, 0xc7, 0xa7, 0xc2, 0xbc, 0xc8, 0x83, + 0x58, 0xc7, 0x89, 0xc7, 0xaa, 0xc9, 0x85, 0x3e, 0xc6, 0x92, 0xc7, 0x94, 0xc3, 0x92, + 0xc3, 0xa0, 0xc3, 0xb4, 0xc6, 0xa6, 0xcd, 0xb0, 0xc8, 0xa8, 0xc7, 0xa3, 0xe2, 0xb1, + 0xa3, 0x7b, 0xc6, 0x92, 0xc4, 0x91, 0xc8, 0xac, 0x50, 0xc8, 0x8b, 0xc4, 0xa9, 0xe1, + 0x9b, 0x90, 0xc4, 0xb5, 0xc8, 0x8e, 0xc3, 0xb7, 0xe2, 0xb1, 0xa2, 0xc6, 0xa1, 0xc3, + 0xb1, 0xc3, 0xba, 0x43, 0xce, 0x89, 0xc8, 0x98, 0x59, 0xcd, 0xbc, 0xe1, 0x9a, 0xa7, + 0xc8, 0xa0, 0xc6, 0x85, 0x5a, 0xc2, 0xb2, 0xc5, 0xbb, 0xc4, 0xb3, 0xc6, 0x8d, 0xc4, + 0xa6, 0xc2, 0xbd, 0xc4, 0x89, 0xe1, 0x9b, 0x9e, 0xc3, 0xae, 0xc4, 0x94, 0xc2, 0xb3, + 0xc5, 0x86, 0xc6, 0x8b, 0xc6, 0xb7, 0x2c, 0xc3, 0x9f, 0xc7, 0x80, 0xc4, 0x87, 0xc4, + 0xb0, 0xc8, 0x81, 0xc4, 0xa7, 0xce, 0x88, 0xc5, 0x86, 0xc5, 0x87, 0xe1, 0x9a, 0xa0, + 0xc6, 0x9e, 0xc6, 0x8d, 0xc7, 0x97, 0xc8, 0x9e, 0xc5, 0xb7, 0xc4, 0x9c, 0xc2, 0xba, + 0xc3, 0xac, 0xe1, 0x9b, 0x8e, 0xe1, 0x9a, 0xb6, 0x6d, 0xc5, 0x8c, 0x6d, 0xc2, 0xaf, + 0xc4, 0xa9, 0xc4, 0x97, 0xc3, 0x89, 0x4c, 0xc5, 0x9f, 0xc6, 0xbd, 0xc6, 0x8c, 0x68, + 0xc5, 0xab, 0xce, 0x84, 0xc2, 0xb2, 0xce, 0x8a, 0xc6, 0xa0, 0xc7, 0xb5, 0xc6, 0xbc, + 0xc3, 0x84, 0xc6, 0xbd, 0xc5, 0xad, 0xc3, 0x84, 0xe1, 0x9b, 0xaf, 0xe2, 0xb1, 0xbc, + 0xc6, 0xa8, 0xc3, 0x8d, 0xe2, 0xb1, 0xb2, 0xc3, 0xb9, 0xc9, 0x8f, 0x33, 0xc8, 0x8a, + 0xc4, 0xb5, 0xc6, 0x8a, 0xc4, 0x9f, 0xc8, 0x84, 0xc4, 0x9c, 0xc4, 0x9f, 0xc7, 0xa0, + 0xc8, 0x8d, 0xc7, 0x88, 0xe2, 0xb1, 0xb7, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0xad, 0x60, + 0xc4, 0x94, 0xc5, 0x80, 0xc8, 0x96, 0xc6, 0xb3, + ], + asset_base: [ + 0x70, 0xc1, 0x47, 0xec, 0x23, 0x32, 0x10, 0xed, 0xdf, 0xab, 0x14, 0xcb, 0xca, 0x72, + 0x4d, 0xd2, 0x8e, 0x2b, 0xc5, 0x7f, 0xb7, 0xb0, 0xd3, 0x44, 0x6d, 0x79, 0x7f, 0x94, + 0xbc, 0xeb, 0xd0, 0xb8, + ], + }, + TestVector { + key: [ + 0xe6, 0xdf, 0x3e, 0xbc, 0x84, 0x4c, 0x0c, 0x39, 0xcb, 0x25, 0xac, 0x91, 0xd6, 0xc1, + 0xd9, 0x20, 0x0f, 0x18, 0xfa, 0x7e, 0x8c, 0x93, 0x4c, 0x4d, 0x0c, 0x30, 0x9d, 0x79, + 0xb0, 0x4a, 0xb4, 0x43, + ], + description: [ + 0xe1, 0x9a, 0xa5, 0xc4, 0x80, 0xc3, 0x85, 0xc5, 0xa4, 0xc5, 0xbb, 0xc7, 0xbf, 0x34, + 0xc9, 0x84, 0xc7, 0x81, 0xc5, 0xbe, 0xc7, 0xbc, 0xe1, 0x9b, 0x97, 0xc5, 0x9e, 0xe2, + 0xb1, 0xbc, 0x37, 0xc8, 0x83, 0x30, 0xc8, 0x84, 0xc6, 0xb3, 0xc8, 0x97, 0xc6, 0xac, + 0xc4, 0xa0, 0x51, 0xc7, 0xab, 0xc8, 0xa3, 0xc3, 0xa9, 0xc5, 0x92, 0xc3, 0x8d, 0xc2, + 0xa3, 0xc5, 0xb9, 0xc8, 0xab, 0xc5, 0xa1, 0x70, 0xc7, 0x85, 0xc7, 0xbf, 0xcd, 0xbd, + 0xc6, 0xab, 0x4c, 0xe1, 0x9a, 0xa5, 0x36, 0xc5, 0xa1, 0xc4, 0xad, 0x4c, 0xc8, 0x92, + 0xc6, 0x9e, 0xc4, 0xbd, 0xc5, 0x95, 0xc3, 0xb4, 0x56, 0xc3, 0xb0, 0xc8, 0xa8, 0xe1, + 0x9a, 0xbf, 0xc4, 0x98, 0xc8, 0xaa, 0x33, 0xc4, 0x97, 0xe1, 0x9a, 0xb2, 0xc9, 0x86, + 0xc2, 0xb1, 0xe1, 0x9b, 0xa2, 0xe1, 0x9b, 0x97, 0xc5, 0xa6, 0x4b, 0xc3, 0x88, 0xe1, + 0x9a, 0xac, 0xce, 0x86, 0xc3, 0x8a, 0xc4, 0x98, 0xc4, 0x89, 0x48, 0xc7, 0xad, 0xe1, + 0x9b, 0x8f, 0xe1, 0x9b, 0xa8, 0xcd, 0xb2, 0xc3, 0xb1, 0xc4, 0xa6, 0xc3, 0xb2, 0xc4, + 0xb1, 0xc8, 0xb4, 0xc3, 0xa9, 0xc9, 0x8d, 0xc7, 0xb6, 0xc4, 0xa0, 0xc6, 0x9b, 0xc6, + 0xbd, 0xc7, 0xaf, 0xc3, 0x9c, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x96, 0xc3, 0x87, 0xcd, + 0xb4, 0xc6, 0x8c, 0xcd, 0xb7, 0xc7, 0xba, 0xc3, 0x94, 0xc8, 0xa3, 0xc3, 0x9e, 0xe1, + 0x9a, 0xa9, 0xc6, 0x98, 0xc6, 0x8a, 0xc5, 0xb6, 0xc9, 0x8b, 0x59, 0xcd, 0xbc, 0xc6, + 0x91, 0xc6, 0xa1, 0xc4, 0x8a, 0xe1, 0x9b, 0xad, 0x31, 0xc9, 0x89, 0xc4, 0x97, 0xc3, + 0xa4, 0xc4, 0x8f, 0xce, 0x8a, 0xe1, 0x9b, 0x8c, 0xc3, 0x9c, 0xc3, 0x89, 0xc6, 0x83, + 0xc9, 0x81, 0xc8, 0x95, 0xc4, 0x9e, 0x39, 0xc8, 0x86, 0xc7, 0x97, 0xc7, 0x87, 0xc2, + 0xa8, 0x23, 0xc3, 0x90, 0xcd, 0xb0, 0xc3, 0x9f, 0xc6, 0xac, 0xc5, 0x81, 0xc7, 0xa2, + 0x78, 0x57, 0xc2, 0xaf, 0xc2, 0xa7, 0x5d, 0xc8, 0x8e, 0x73, 0xe1, 0x9b, 0xa8, 0xc8, + 0x95, 0xc5, 0x99, 0xc2, 0xb3, 0xc5, 0xb8, 0xe1, 0x9a, 0xa8, 0xc8, 0x85, 0xc7, 0x82, + 0xc8, 0x8a, 0x34, 0xc3, 0xbd, 0xe1, 0x9b, 0x99, 0xe1, 0x9b, 0xaa, 0xc8, 0xb2, 0xc5, + 0xa7, 0xc7, 0xb2, 0xc6, 0x98, 0x40, 0xe1, 0x9a, 0xb8, 0xe1, 0x9a, 0xb4, 0x77, 0xc2, + 0xa2, 0xe1, 0x9a, 0xa4, 0xc5, 0x84, 0xe2, 0xb1, 0xa7, 0xc4, 0xbc, 0xc5, 0xb3, 0xe2, + 0xb1, 0xa2, 0xc8, 0xb4, 0xc8, 0xbd, 0xc6, 0x98, 0xc8, 0xa9, 0x78, 0xc8, 0x9b, 0xc3, + 0x85, 0xc5, 0xaf, 0xc5, 0x83, 0x34, 0x5f, 0xc5, 0x88, 0xe1, 0x9a, 0xb3, 0x7d, 0xc4, + 0xa5, 0xc3, 0xb4, 0xe1, 0x9a, 0xb3, 0xc7, 0x8e, 0xc5, 0x86, 0xc4, 0x94, 0xc7, 0x89, + 0xe1, 0x9b, 0x8a, 0xe1, 0x9b, 0xa4, 0xc6, 0x9a, 0xc3, 0x8e, 0xc5, 0xa9, 0xc6, 0xbe, + 0xe2, 0xb1, 0xb5, 0xc4, 0xb2, 0xc3, 0x88, 0xc5, 0xb2, 0xc8, 0xa7, 0xe1, 0x9b, 0x8a, + 0xc4, 0x9f, 0xc7, 0x94, 0xe1, 0x9a, 0xb5, 0xc9, 0x83, 0xc6, 0xb5, 0xe2, 0xb1, 0xa0, + 0xc4, 0xb0, 0x59, 0xe1, 0x9b, 0x9f, 0xc4, 0xa9, 0xc3, 0x96, 0xc7, 0xba, 0xc5, 0xad, + 0xc3, 0xaf, 0xc3, 0xa1, 0xc6, 0x86, 0xc2, 0xb8, 0xe1, 0x9b, 0xa7, 0xc2, 0xb2, 0xc4, + 0x9d, 0xc8, 0x87, 0xc9, 0x89, 0xe1, 0x9a, 0xa8, 0xc4, 0x8a, 0xc5, 0xbe, 0x33, 0xc7, + 0x89, 0xce, 0x8c, 0xc9, 0x85, 0x4b, 0xc7, 0xa6, 0x76, 0xc8, 0xbc, 0xc2, 0xb2, 0xcd, + 0xbb, 0xe1, 0x9b, 0xa5, 0xc8, 0x9d, 0xc7, 0xa1, 0xc7, 0xb3, 0xe1, 0x9a, 0xb5, 0xc7, + 0x94, 0xc4, 0x86, 0xe1, 0x9a, 0xa2, 0xc8, 0xb1, 0xc3, 0x97, 0xc8, 0xb3, 0xe2, 0xb1, + 0xb2, 0xc6, 0xb9, 0xc3, 0xb5, 0x74, 0xc2, 0xb3, + ], + asset_base: [ + 0x85, 0x94, 0x73, 0xb4, 0x98, 0xbb, 0x99, 0x99, 0x4a, 0x06, 0x71, 0x0e, 0x5c, 0xd2, + 0x10, 0x78, 0xa5, 0x22, 0xea, 0xa5, 0xf6, 0xad, 0x2d, 0x22, 0xe5, 0x12, 0x57, 0x6d, + 0x8c, 0x89, 0x65, 0x21, + ], + }, + TestVector { + key: [ + 0xdb, 0x1f, 0x0a, 0x56, 0x5c, 0x8c, 0x06, 0xa6, 0x3d, 0x4f, 0x75, 0x92, 0x62, 0x55, + 0xf4, 0xfa, 0x3c, 0x76, 0x44, 0x23, 0xc0, 0x49, 0x55, 0x02, 0x4e, 0xa0, 0x3b, 0xba, + 0x63, 0x63, 0x6c, 0x55, + ], + description: [ + 0xc6, 0xa7, 0xe1, 0x9b, 0x8e, 0xc6, 0x8d, 0xc6, 0x88, 0xc2, 0xa3, 0xc4, 0xbe, 0xc6, + 0x93, 0xc5, 0x95, 0xe1, 0x9b, 0x88, 0xc3, 0x82, 0xc4, 0xa5, 0x32, 0xc7, 0x95, 0xc9, + 0x88, 0xc5, 0xbd, 0xe1, 0x9b, 0x85, 0xc9, 0x84, 0xc3, 0x80, 0xe2, 0xb1, 0xa8, 0xc6, + 0xac, 0xe1, 0x9b, 0x82, 0xc5, 0x82, 0x29, 0xc4, 0x80, 0xc8, 0x9c, 0xc6, 0x88, 0xc3, + 0xba, 0xc8, 0xa1, 0xe1, 0x9a, 0xb8, 0xc3, 0xbb, 0xc3, 0xb8, 0xc6, 0x90, 0x24, 0xc8, + 0x8b, 0xe1, 0x9a, 0xa1, 0x31, 0xc8, 0x9c, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x82, 0xc2, + 0xb6, 0xc6, 0xb1, 0xe1, 0x9b, 0x87, 0x49, 0xc4, 0xba, 0xe2, 0xb1, 0xb5, 0x32, 0xc6, + 0x99, 0xc7, 0x9b, 0xc7, 0x85, 0x67, 0xc6, 0xa5, 0xc9, 0x8b, 0x45, 0x77, 0xc6, 0x9e, + 0x3d, 0xc4, 0x82, 0xe2, 0xb1, 0xaf, 0xc6, 0x87, 0xe1, 0x9a, 0xb0, 0xe1, 0x9a, 0xa0, + 0xc9, 0x88, 0xc3, 0x98, 0xc3, 0xa7, 0xc6, 0x9b, 0xc7, 0x9c, 0xc4, 0xb5, 0xc3, 0xaf, + 0xc4, 0xa9, 0xc3, 0xb8, 0xc5, 0xaf, 0xc2, 0xac, 0xc9, 0x8a, 0xe1, 0x9b, 0x8c, 0x47, + 0xe1, 0x9b, 0xaa, 0xe1, 0x9a, 0xb6, 0x24, 0xc8, 0x9c, 0x4f, 0xc8, 0xb7, 0x64, 0xe1, + 0x9a, 0xad, 0xc9, 0x87, 0xc2, 0xbe, 0xe1, 0x9b, 0x89, 0x6c, 0xe2, 0xb1, 0xac, 0xc5, + 0x8e, 0xe1, 0x9b, 0x87, 0xe2, 0xb1, 0xb0, 0xc3, 0xb1, 0xc3, 0x8e, 0xc3, 0x89, 0xe1, + 0x9b, 0x9f, 0xc4, 0xb7, 0x42, 0xc6, 0xb6, 0xc6, 0x9d, 0xc2, 0xa7, 0xc2, 0xb1, 0xc4, + 0xa5, 0xc6, 0xa3, 0xc8, 0x84, 0xc7, 0x85, 0x74, 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xaf, + 0xc7, 0x87, 0x5b, 0xc6, 0xa7, 0xc4, 0x91, 0xc5, 0x95, 0xc8, 0xa6, 0xc4, 0xb0, 0xe1, + 0x9b, 0xac, 0xe1, 0x9b, 0x8b, 0xc3, 0x95, 0xe1, 0x9a, 0xaf, 0xc3, 0x85, 0xc4, 0xbf, + 0xc2, 0xb0, 0xc5, 0x97, 0xc5, 0xa3, 0xc5, 0xb2, 0xc6, 0xad, 0x60, 0xc5, 0x8b, 0xc3, + 0x88, 0xe2, 0xb1, 0xb4, 0xc2, 0xbd, 0xc7, 0xbb, 0xe2, 0xb1, 0xab, 0xc4, 0x99, 0xc4, + 0x91, 0x21, 0xc9, 0x8d, 0xc6, 0x92, 0xc7, 0x95, 0x32, 0xe1, 0x9b, 0xa3, 0xc5, 0x86, + 0xc7, 0x95, 0xc8, 0xba, 0xe2, 0xb1, 0xbb, 0xc3, 0x89, 0xc6, 0x9c, 0xc6, 0x92, 0xe2, + 0xb1, 0xab, 0xc4, 0xaf, 0xc5, 0x81, 0xc4, 0x80, 0xc3, 0x98, 0xc4, 0xad, 0xc5, 0x8b, + 0xc6, 0xb5, 0x53, 0xc7, 0x8a, 0x43, 0xc4, 0x95, 0xc4, 0xad, 0xc8, 0xba, 0xe1, 0x9a, + 0xb8, 0x7b, 0xc3, 0xb2, 0x33, 0xc2, 0xb6, 0xc5, 0x8b, 0xe1, 0x9a, 0xb5, 0x74, 0x34, + 0xc8, 0x9f, 0xc6, 0x83, 0x3d, 0xc2, 0xb1, 0x6b, 0xc4, 0xa8, 0xc3, 0xb5, 0xc7, 0x8c, + 0xc7, 0x84, 0x2e, 0xc8, 0x85, 0xc4, 0x99, 0xc7, 0x8e, 0x60, 0x4b, 0xc4, 0x93, 0xe2, + 0xb1, 0xbe, 0xc7, 0x88, 0xc3, 0x86, 0x48, 0x5d, 0xc6, 0xa1, 0x78, 0xc7, 0xaa, 0xc7, + 0x85, 0x29, 0xc7, 0x82, 0xc3, 0x9c, 0xc6, 0xbe, 0xe1, 0x9b, 0x82, 0x2c, 0xc8, 0xa3, + 0xc8, 0x95, 0xc8, 0xbe, 0xc3, 0x94, 0xc8, 0xad, 0xcd, 0xb2, 0xc3, 0xa2, 0xc4, 0xbd, + 0xe1, 0x9b, 0x98, 0xe2, 0xb1, 0xac, 0xc3, 0x8d, 0xc3, 0x99, 0xc4, 0xb1, 0xe1, 0x9b, + 0x83, 0xe1, 0x9a, 0xb3, 0x72, 0xc6, 0xa2, 0x37, 0xe1, 0x9b, 0xaf, 0xc3, 0x98, 0xc4, + 0x99, 0xc3, 0xa0, 0xc7, 0xb5, 0xc6, 0x97, 0x6d, 0xc5, 0xb0, 0xc7, 0xa6, 0xe2, 0xb1, + 0xa5, 0xc5, 0xa8, 0xc3, 0xa8, 0xc5, 0x9b, 0xe1, 0x9a, 0xa1, 0xc7, 0xb5, 0x78, 0xe2, + 0xb1, 0xbb, 0xe1, 0x9b, 0xa7, 0xc6, 0xae, 0xe1, 0x9a, 0xbb, 0xc4, 0xba, 0xc5, 0xa7, + 0xc4, 0x86, 0xc5, 0x94, 0xc8, 0xb4, 0xc3, 0xa3, 0xc8, 0x83, 0xc8, 0x8a, 0xc5, 0xb6, + 0xcd, 0xbc, 0xe1, 0x9a, 0xbc, 0xe2, 0xb1, 0xa8, + ], + asset_base: [ + 0xb2, 0xea, 0x85, 0x07, 0x94, 0x73, 0xf8, 0x06, 0xce, 0x30, 0xca, 0xe0, 0xbf, 0x6c, + 0xb9, 0xc9, 0xeb, 0x91, 0x72, 0xc0, 0xb9, 0x86, 0x47, 0x7a, 0xb9, 0x04, 0xd1, 0xfa, + 0x68, 0x49, 0x01, 0x2e, + ], + }, + TestVector { + key: [ + 0x98, 0x9f, 0xc7, 0x01, 0x45, 0xd2, 0xfb, 0xb4, 0xd2, 0xe2, 0x79, 0xe5, 0xf9, 0x5d, + 0x72, 0x9f, 0x6a, 0xf4, 0xe9, 0x83, 0x28, 0x53, 0xf5, 0x97, 0xaf, 0x2f, 0xfb, 0xfb, + 0x88, 0xa6, 0x6e, 0xba, + ], + description: [ + 0xce, 0x8a, 0xc7, 0xb5, 0xc7, 0xbd, 0xc2, 0xae, 0x66, 0xc6, 0xbd, 0xc8, 0xa0, 0xc7, + 0x85, 0x4f, 0xe1, 0x9b, 0xa4, 0xc3, 0xb4, 0xe1, 0x9b, 0x92, 0xc6, 0xa6, 0xc6, 0x95, + 0xc5, 0x97, 0xc6, 0x97, 0xcd, 0xb2, 0xc6, 0x81, 0xc8, 0xaa, 0xe1, 0x9b, 0x8a, 0xc7, + 0xa0, 0xc4, 0xaa, 0xe1, 0x9b, 0xa9, 0x79, 0xe2, 0xb1, 0xb2, 0xc8, 0xba, 0xc3, 0x96, + 0xc8, 0x85, 0xe2, 0xb1, 0xb1, 0xc5, 0x82, 0x2e, 0xc7, 0x8b, 0xc7, 0x85, 0xe2, 0xb1, + 0xbb, 0xe1, 0x9b, 0xab, 0xc9, 0x8a, 0x3c, 0xc3, 0x9b, 0xc8, 0xac, 0xc2, 0xae, 0xc5, + 0x86, 0xc2, 0xbb, 0xc3, 0x89, 0xc8, 0x9a, 0x7b, 0xc2, 0xbe, 0xc7, 0x99, 0xc5, 0xb2, + 0xc4, 0x81, 0xc6, 0xb2, 0xc8, 0x96, 0xc7, 0xb2, 0xc8, 0xba, 0xc5, 0xac, 0xce, 0x88, + 0xc5, 0x94, 0xc3, 0xbd, 0xc8, 0x81, 0xc5, 0x94, 0xc3, 0xad, 0xc7, 0x83, 0x73, 0xc4, + 0xba, 0xe2, 0xb1, 0xad, 0xe1, 0x9a, 0xbb, 0xc5, 0x84, 0xc5, 0xbd, 0x40, 0xc3, 0x9c, + 0xc7, 0xbb, 0xc4, 0xbb, 0xc6, 0xba, 0x67, 0x41, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xba, + 0xc6, 0xa9, 0xe1, 0x9b, 0x8d, 0x48, 0xc4, 0xa8, 0xc7, 0x88, 0xc3, 0x9b, 0xc8, 0x8a, + 0x65, 0xc3, 0xab, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0x8d, 0x52, 0xe1, 0x9a, 0xa1, 0xc8, + 0x8b, 0x29, 0xc3, 0x9a, 0xc7, 0x86, 0xc3, 0x95, 0xe2, 0xb1, 0xa8, 0xe1, 0x9b, 0x8f, + 0xc5, 0x94, 0xc4, 0x8e, 0x44, 0xc6, 0xa2, 0xc5, 0x88, 0x3e, 0x7a, 0xc8, 0x9f, 0xe1, + 0x9a, 0xa5, 0xc4, 0x9b, 0xc5, 0xa7, 0xc5, 0x91, 0xc3, 0x8e, 0xc7, 0xb2, 0xc4, 0x83, + 0x38, 0xe2, 0xb1, 0xb4, 0xc5, 0xb9, 0xc4, 0xbb, 0xc7, 0x88, 0x4d, 0xc2, 0xa5, 0xe2, + 0xb1, 0xaf, 0xe1, 0x9a, 0xaa, 0x72, 0xe2, 0xb1, 0xba, 0xc8, 0x8b, 0xe1, 0x9b, 0xaa, + 0xc7, 0x90, 0xc5, 0xaa, 0x29, 0xc7, 0xa8, 0xc5, 0x90, 0xc7, 0xa9, 0xcd, 0xb7, 0xc8, + 0xa9, 0xc8, 0x88, 0xc6, 0x8a, 0xc4, 0x84, 0xc4, 0xa2, 0xc7, 0xa2, 0xe1, 0x9a, 0xba, + 0xc2, 0xb4, 0xe1, 0x9b, 0x8d, 0xc6, 0x91, 0xcd, 0xb1, 0xc5, 0xa5, 0xc3, 0xb3, 0x39, + 0xe1, 0x9b, 0x85, 0xc4, 0xbe, 0xc4, 0x9e, 0xcd, 0xb1, 0xc6, 0x83, 0x69, 0xc3, 0xba, + 0xe1, 0x9b, 0x95, 0xc2, 0xbf, 0xc6, 0xbd, 0x53, 0xc7, 0xb9, 0xc8, 0x9b, 0x5b, 0xc9, + 0x8c, 0xc7, 0xa1, 0xc8, 0xaa, 0xcd, 0xbc, 0xc4, 0xb0, 0xcd, 0xb6, 0xc4, 0x93, 0xc4, + 0xab, 0xe1, 0x9b, 0x86, 0xc6, 0xaf, 0xc5, 0x9b, 0xc2, 0xb3, 0xc3, 0xa3, 0xe1, 0x9a, + 0xb1, 0xe1, 0x9b, 0x8a, 0xc5, 0x90, 0xc6, 0xa5, 0xc2, 0xae, 0x51, 0x5b, 0xce, 0x86, + 0xc9, 0x8c, 0xc7, 0x8f, 0xc6, 0x95, 0xc5, 0x88, 0xc7, 0x82, 0xc5, 0xa2, 0xce, 0x85, + 0xc8, 0x85, 0xc3, 0x85, 0xc7, 0xb1, 0xc7, 0xbe, 0xc8, 0x8c, 0xe1, 0x9b, 0x8d, 0xc8, + 0x90, 0xc4, 0xb6, 0xc3, 0xbf, 0xe1, 0x9b, 0x86, 0xc6, 0xb8, 0xe2, 0xb1, 0xb5, 0xc3, + 0x8e, 0xc8, 0x9b, 0xcd, 0xb7, 0xc5, 0x94, 0xc5, 0x86, 0xc5, 0x9f, 0xc4, 0xb0, 0xc7, + 0xa6, 0xc2, 0xbd, 0x70, 0xc6, 0xac, 0xc8, 0xb7, 0xe1, 0x9b, 0x96, 0xc5, 0xbe, 0xc5, + 0x97, 0xe1, 0x9a, 0xb9, 0xc3, 0xa7, 0xe2, 0xb1, 0xb4, 0xc5, 0xb6, 0x24, 0x49, 0x26, + 0xc5, 0x82, 0xc9, 0x8c, 0xc6, 0x9d, 0xc5, 0x93, 0xc3, 0x85, 0xc3, 0x98, 0xc8, 0xbe, + 0x4e, 0xc5, 0xae, 0x44, 0x67, 0xe1, 0x9a, 0xa5, 0xc7, 0xb1, 0xc4, 0xb6, 0xc7, 0xaf, + 0x5d, 0xc3, 0xb9, 0xc3, 0xb5, 0xc3, 0xab, 0xc7, 0x83, 0xc7, 0xb3, 0xe1, 0x9b, 0x99, + 0xc4, 0x9d, 0xc3, 0x83, 0xc3, 0xb4, 0xc5, 0xb2, 0xc7, 0xbe, 0x5e, 0xcd, 0xba, 0xc9, + 0x87, 0xe2, 0xb1, 0xbd, 0xc8, 0x8f, 0xc9, 0x8c, + ], + asset_base: [ + 0x1a, 0x51, 0xbf, 0x64, 0x82, 0x22, 0x09, 0x2a, 0x98, 0x5b, 0x0e, 0x94, 0xfa, 0x1d, + 0xb4, 0xb4, 0xbf, 0xad, 0x07, 0x8f, 0xbe, 0x75, 0xc1, 0xbf, 0x83, 0x1c, 0x47, 0xd3, + 0x54, 0x6f, 0xbc, 0x38, + ], + }, + TestVector { + key: [ + 0x1d, 0xa0, 0x2d, 0x7e, 0x6a, 0x75, 0x4b, 0xe4, 0xde, 0xfa, 0x04, 0x90, 0x29, 0xc7, + 0x94, 0x8b, 0x5e, 0xd2, 0x5b, 0x4d, 0x22, 0xbf, 0x87, 0x27, 0x0b, 0x9d, 0x32, 0xda, + 0x52, 0x81, 0x92, 0x24, + ], + description: [ + 0xe1, 0x9b, 0x9c, 0xe1, 0x9a, 0xa5, 0xc5, 0xb7, 0x2b, 0xc3, 0x81, 0xc3, 0x8d, 0xc8, + 0xb2, 0xc8, 0xb5, 0xc5, 0x81, 0xc5, 0x9e, 0xc7, 0xa7, 0xe1, 0x9b, 0x8b, 0xc7, 0xb7, + 0xe1, 0x9b, 0x80, 0x6d, 0xc8, 0x94, 0x64, 0xc6, 0x88, 0xe2, 0xb1, 0xa6, 0xc6, 0x8f, + 0xc9, 0x82, 0x5d, 0xe1, 0x9a, 0xae, 0xe2, 0xb1, 0xa8, 0xc2, 0xb1, 0xc7, 0xa3, 0xc8, + 0x87, 0xc3, 0xb4, 0xe2, 0xb1, 0xbe, 0xc6, 0xba, 0xc3, 0x9d, 0xc8, 0xbd, 0xe1, 0x9a, + 0xae, 0x74, 0xe2, 0xb1, 0xa2, 0xc8, 0x9f, 0xcd, 0xb2, 0xc4, 0x9a, 0xe1, 0x9a, 0xb7, + 0xc7, 0xa4, 0xe1, 0x9a, 0xa2, 0xc5, 0x95, 0xc7, 0x85, 0xc7, 0xa3, 0x4c, 0xc7, 0xb6, + 0xcd, 0xbd, 0x26, 0xc7, 0x9b, 0xc4, 0xb4, 0xc6, 0xa0, 0xe1, 0x9a, 0xbe, 0xce, 0x85, + 0xc2, 0xae, 0x38, 0xc7, 0xab, 0xc6, 0x87, 0xc5, 0xab, 0xc4, 0xb2, 0xc6, 0xb5, 0xc8, + 0xb3, 0xc7, 0xa6, 0xc3, 0xbd, 0xc5, 0xba, 0x4a, 0xc7, 0x8e, 0xc7, 0x8e, 0xc2, 0xb2, + 0x49, 0xc5, 0xb1, 0x5a, 0xc3, 0xaa, 0xc6, 0x8b, 0xc5, 0x86, 0x4f, 0xc8, 0xbd, 0x49, + 0xc3, 0x98, 0xc5, 0x8e, 0xc9, 0x8a, 0xc8, 0x92, 0x36, 0xe1, 0x9b, 0xad, 0xe1, 0x9b, + 0x9c, 0xc3, 0xa7, 0xc8, 0xab, 0xc4, 0xac, 0xe1, 0x9a, 0xa9, 0xc8, 0xbe, 0xc7, 0xb2, + 0xe1, 0x9a, 0xb3, 0xc8, 0x8c, 0xc7, 0x8f, 0xe2, 0xb1, 0xa3, 0xc5, 0xaf, 0xc6, 0x9f, + 0xc7, 0x92, 0xe1, 0x9b, 0xad, 0x4b, 0xc2, 0xb1, 0xc4, 0x9c, 0xcd, 0xbd, 0xc5, 0xba, + 0xc6, 0xb2, 0xe2, 0xb1, 0xb7, 0xc6, 0xb1, 0xc2, 0xba, 0xc6, 0xa8, 0xc8, 0x89, 0xc5, + 0x97, 0xc5, 0xaf, 0xe1, 0x9b, 0x8e, 0xc5, 0x9d, 0xc4, 0xa4, 0xc3, 0xb9, 0xc8, 0x8b, + 0xc7, 0x84, 0xc5, 0xaa, 0x7b, 0x78, 0xe1, 0x9b, 0x81, 0x60, 0x5e, 0xc3, 0x91, 0xc6, + 0xb4, 0x4f, 0xc9, 0x8d, 0xc4, 0xa3, 0xc5, 0x90, 0xe1, 0x9a, 0xbd, 0xc5, 0x93, 0xc3, + 0xab, 0xc6, 0x9e, 0xc7, 0xb5, 0xc5, 0xa5, 0xc7, 0xba, 0xe2, 0xb1, 0xb9, 0xe1, 0x9a, + 0xa9, 0x2a, 0xe1, 0x9a, 0xae, 0xc3, 0xb7, 0xc9, 0x87, 0x4c, 0xc7, 0x86, 0xc9, 0x81, + 0xc6, 0xba, 0xc8, 0x87, 0xc7, 0x96, 0x57, 0xc5, 0xab, 0xc2, 0xa5, 0xc3, 0x85, 0xc8, + 0x8f, 0xe1, 0x9b, 0x89, 0xc2, 0xb6, 0xc2, 0xa7, 0xc7, 0x80, 0xc8, 0xb4, 0xcd, 0xb4, + 0xc9, 0x88, 0xc8, 0x85, 0xc7, 0xb7, 0xc8, 0x99, 0x3d, 0xc7, 0x9f, 0xc7, 0x8f, 0xc4, + 0xa0, 0xc7, 0xb6, 0xc4, 0x80, 0xc3, 0x85, 0xe1, 0x9a, 0xbc, 0xc3, 0x90, 0xc4, 0xb0, + 0xc4, 0x83, 0xe1, 0x9a, 0xa4, 0xc9, 0x8e, 0x36, 0xc4, 0xb2, 0xc4, 0x94, 0xc6, 0xbf, + 0xe2, 0xb1, 0xbd, 0xc5, 0xae, 0xc2, 0xae, 0xe1, 0x9b, 0xa9, 0xc5, 0x96, 0xc8, 0x9d, + 0xc5, 0xb7, 0xc3, 0x8c, 0xc8, 0xae, 0xe2, 0xb1, 0xaf, 0xc5, 0xa6, 0xc4, 0xac, 0x24, + 0x6d, 0xc8, 0x99, 0xc7, 0x9d, 0x2c, 0xc2, 0xac, 0xc6, 0xbe, 0xc2, 0xac, 0xc9, 0x88, + 0xc5, 0xa8, 0xc6, 0xa1, 0xcd, 0xb2, 0xc6, 0xa7, 0x5d, 0xc8, 0xa0, 0xc8, 0xb2, 0xc4, + 0x83, 0xc3, 0xb9, 0xc4, 0xa0, 0xc5, 0x86, 0x54, 0x5d, 0xe1, 0x9b, 0xb0, 0xc5, 0x94, + 0x35, 0xe1, 0x9a, 0xb7, 0xe2, 0xb1, 0xa6, 0xc8, 0xa9, 0xc8, 0xa6, 0xcd, 0xb6, 0xc8, + 0xa1, 0x6b, 0xc5, 0x9b, 0x73, 0xc3, 0x98, 0xc3, 0xa3, 0xc5, 0xb8, 0xe1, 0x9b, 0x9f, + 0xc5, 0xb5, 0xc5, 0x99, 0xc4, 0xa2, 0xc3, 0x81, 0xc9, 0x87, 0xe1, 0x9a, 0xac, 0x59, + 0xc8, 0xbb, 0xc6, 0x8b, 0xc4, 0xa8, 0xc4, 0x95, 0xc8, 0xb9, 0xc2, 0xa6, 0xc5, 0xbc, + 0xc4, 0x87, 0xc5, 0x94, 0xc4, 0x9e, 0x5e, 0xc3, 0xb0, 0x2a, 0x3a, 0xe1, 0x9b, 0x81, + 0xc7, 0xab, 0xc5, 0x92, 0xc8, 0x8c, 0x5a, 0x5a, + ], + asset_base: [ + 0xb1, 0x08, 0xcf, 0xf7, 0x04, 0xbf, 0xce, 0x2b, 0xdb, 0x86, 0xdb, 0xb8, 0x40, 0x3f, + 0x02, 0x20, 0x3f, 0x1c, 0xa1, 0x50, 0x2d, 0x5e, 0x24, 0xe2, 0x21, 0xc2, 0x23, 0xd7, + 0xeb, 0x82, 0xb2, 0x18, + ], + }, + TestVector { + key: [ + 0x72, 0xab, 0x8e, 0x45, 0x8e, 0xd4, 0xc8, 0xf2, 0xc5, 0xba, 0xa1, 0x18, 0x50, 0xac, + 0xff, 0x71, 0x55, 0xd6, 0xad, 0x0d, 0xc9, 0x81, 0x55, 0x7b, 0x0a, 0x63, 0xab, 0xcb, + 0xf4, 0xa6, 0x8d, 0xe3, + ], + description: [ + 0x6d, 0xc3, 0xbf, 0xc7, 0xa9, 0xc6, 0x93, 0xc4, 0x8b, 0xc4, 0xb2, 0xc8, 0xba, 0xc6, + 0xab, 0x2d, 0xc7, 0xa4, 0xe2, 0xb1, 0xa5, 0xc6, 0x8f, 0xc7, 0x9d, 0xe2, 0xb1, 0xb0, + 0xc8, 0xaa, 0xc3, 0x91, 0xc7, 0xbb, 0xe2, 0xb1, 0xaa, 0xe2, 0xb1, 0xa8, 0xc6, 0x97, + 0x24, 0xe1, 0x9b, 0xa6, 0x3d, 0xc3, 0x96, 0xc8, 0xaf, 0xc6, 0xb6, 0xc3, 0xbb, 0xc6, + 0xad, 0xc5, 0x81, 0xc8, 0xbb, 0xc7, 0x91, 0xc6, 0x93, 0xc6, 0x8c, 0x2c, 0xc7, 0x9f, + 0xc6, 0xa2, 0x67, 0xc6, 0xb3, 0xe2, 0xb1, 0xa0, 0xc2, 0xbe, 0xc4, 0x90, 0x4d, 0xe1, + 0x9b, 0x99, 0xc6, 0x92, 0xe1, 0x9a, 0xa2, 0xe1, 0x9a, 0xb7, 0xe1, 0x9a, 0xa9, 0xe1, + 0x9b, 0x94, 0xc6, 0xa1, 0x4a, 0xc4, 0xb8, 0xe1, 0x9a, 0xb9, 0xc2, 0xaa, 0xc7, 0x8e, + 0xe2, 0xb1, 0xa7, 0x25, 0xc4, 0xa5, 0xc6, 0x9a, 0xc5, 0x82, 0xc4, 0xb2, 0xe2, 0xb1, + 0xbf, 0xc8, 0x91, 0xc3, 0x8e, 0xcd, 0xb4, 0xc8, 0x82, 0xc4, 0xb2, 0xc8, 0xb4, 0xc5, + 0x9f, 0xc5, 0x9b, 0xe1, 0x9a, 0xb0, 0xc8, 0xa8, 0xc3, 0x9f, 0xc7, 0x9e, 0xe1, 0x9b, + 0x93, 0xe1, 0x9a, 0xaa, 0xc7, 0x94, 0xe2, 0xb1, 0xa7, 0x77, 0xc3, 0x9e, 0xc8, 0x85, + 0xc2, 0xab, 0x5f, 0xc3, 0x91, 0xc2, 0xa5, 0xc6, 0xa7, 0xc4, 0x80, 0xe1, 0x9b, 0x92, + 0xc2, 0xbf, 0xcd, 0xb4, 0xc5, 0xb9, 0xc8, 0xa1, 0xc8, 0x8c, 0xc4, 0x98, 0xc3, 0xa6, + 0xc2, 0xab, 0xc4, 0x8d, 0xe1, 0x9a, 0xb6, 0xc7, 0x97, 0xc3, 0xa7, 0xc7, 0x99, 0xc3, + 0x82, 0x65, 0xc7, 0x8f, 0xe1, 0x9b, 0x87, 0xc5, 0xa3, 0xe1, 0x9b, 0x96, 0xc7, 0x8a, + 0xe1, 0x9b, 0x9f, 0xc6, 0xb0, 0x4e, 0x50, 0xc6, 0xb6, 0xc2, 0xa7, 0xc8, 0xa7, 0xc5, + 0xbd, 0xc6, 0x96, 0xc6, 0x98, 0xc7, 0x96, 0x30, 0xc8, 0xa7, 0xc6, 0x8c, 0x2e, 0xc8, + 0x8c, 0x62, 0xe1, 0x9a, 0xbf, 0xc4, 0x8c, 0xc7, 0x89, 0xe1, 0x9a, 0xa4, 0xc8, 0xa5, + 0x45, 0xcd, 0xbe, 0xe1, 0x9b, 0xb0, 0xc3, 0x90, 0x40, 0xc3, 0xbe, 0xc4, 0x8f, 0xc6, + 0x89, 0xc5, 0xb9, 0x6b, 0xc8, 0xbd, 0xc3, 0x97, 0xe1, 0x9a, 0xa0, 0xc7, 0xb3, 0xc5, + 0xb7, 0xc7, 0x85, 0xc3, 0x92, 0xe2, 0xb1, 0xac, 0xc4, 0xb0, 0xc5, 0xbc, 0xc6, 0x9d, + 0xc6, 0xbb, 0xc6, 0x82, 0xc6, 0x94, 0xc5, 0xb8, 0xc9, 0x8f, 0xc5, 0xbc, 0xc5, 0xad, + 0xc7, 0x8f, 0xc5, 0xb0, 0xc7, 0x89, 0xc7, 0x82, 0xc6, 0x9c, 0x41, 0xc6, 0xbe, 0xc7, + 0x93, 0xc5, 0xa2, 0xc6, 0xa5, 0xc7, 0x9c, 0xc5, 0x8d, 0xc7, 0x9f, 0xe1, 0x9b, 0x80, + 0xc4, 0xba, 0xce, 0x8a, 0xc2, 0xaf, 0xc5, 0x8f, 0x79, 0xc5, 0xb7, 0xc6, 0x87, 0x48, + 0xc2, 0xa9, 0xc4, 0xb4, 0xc3, 0x9b, 0xc8, 0x87, 0xc9, 0x8c, 0xc8, 0xb2, 0xe1, 0x9b, + 0xa3, 0x68, 0xe2, 0xb1, 0xb6, 0xc5, 0x8c, 0xc2, 0xaa, 0x64, 0xc5, 0x85, 0x48, 0xc5, + 0x87, 0x54, 0xe2, 0xb1, 0xaf, 0xc5, 0x88, 0xc4, 0x8f, 0xc5, 0x94, 0xe1, 0x9b, 0xa4, + 0xe1, 0x9b, 0xa1, 0xc5, 0xa8, 0xc7, 0x92, 0xc4, 0xbc, 0xc4, 0xa8, 0xc8, 0x9f, 0xc3, + 0xbd, 0xe1, 0x9b, 0xab, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xa3, 0xc5, 0xac, 0xc8, 0x8e, + 0xc7, 0xbf, 0xc3, 0xbb, 0xe1, 0x9b, 0x9a, 0xc5, 0x86, 0xc4, 0xae, 0xe2, 0xb1, 0xa9, + 0xc7, 0x8a, 0x25, 0xc7, 0xbc, 0xc8, 0x89, 0x31, 0xc4, 0x84, 0xc3, 0x9c, 0xc2, 0xbd, + 0xc3, 0x90, 0xe2, 0xb1, 0xb9, 0xc7, 0x97, 0xc5, 0xb7, 0xc3, 0x81, 0xc8, 0xa1, 0x6d, + 0xc7, 0xa4, 0xc8, 0x9f, 0xc9, 0x8f, 0xe1, 0x9b, 0x95, 0xe1, 0x9b, 0x9a, 0x3e, 0xc3, + 0x94, 0xc7, 0x94, 0xc4, 0xbc, 0xcd, 0xb4, 0xc8, 0xbd, 0xc7, 0xb1, 0x39, 0xc3, 0x8c, + 0xe2, 0xb1, 0xa5, 0xc8, 0x82, 0xc7, 0x8b, 0x5a, + ], + asset_base: [ + 0x9c, 0x64, 0x87, 0xfa, 0x7e, 0x3e, 0xd4, 0xc1, 0x7c, 0x02, 0x43, 0x93, 0x55, 0x14, + 0xc9, 0x45, 0x4a, 0x6f, 0x21, 0x3f, 0x7b, 0x1c, 0x5b, 0x32, 0xab, 0xd5, 0xa8, 0x6e, + 0x49, 0xe1, 0x35, 0x2d, + ], + }, + TestVector { + key: [ + 0x0e, 0xf9, 0x1a, 0x2b, 0x56, 0xac, 0x5f, 0x19, 0xd1, 0xc9, 0xfb, 0x24, 0x98, 0x6c, + 0x01, 0x36, 0x2d, 0x66, 0x39, 0x16, 0x0c, 0x27, 0x5b, 0x28, 0x02, 0x46, 0x50, 0x05, + 0x14, 0x96, 0x98, 0x44, + ], + description: [ + 0x49, 0xc2, 0xa7, 0xc3, 0xb0, 0x67, 0xe1, 0x9b, 0xa1, 0xc6, 0xa6, 0xc6, 0x95, 0xe1, + 0x9a, 0xa8, 0xc7, 0xae, 0xc8, 0xa1, 0xc7, 0xbc, 0xe1, 0x9a, 0xba, 0xc8, 0x86, 0xe2, + 0xb1, 0xa9, 0xc6, 0x8e, 0xe1, 0x9a, 0xb3, 0xe1, 0x9a, 0xa7, 0xc8, 0x88, 0xc3, 0x97, + 0xc7, 0xac, 0xc7, 0x97, 0x64, 0xc7, 0xae, 0xc5, 0xab, 0xc3, 0x9c, 0xc4, 0x8e, 0xc3, + 0x97, 0xc6, 0x83, 0xc4, 0x9e, 0xc9, 0x89, 0xc4, 0x9a, 0xc2, 0xaf, 0xc2, 0xaa, 0xc7, + 0x92, 0xcd, 0xb1, 0x65, 0xc5, 0x92, 0xe1, 0x9b, 0xa3, 0xc7, 0x83, 0x4c, 0x63, 0xc2, + 0xa5, 0xc4, 0xa5, 0x42, 0xc3, 0x9a, 0xc5, 0x85, 0xc5, 0x80, 0xc5, 0x9e, 0xc3, 0xa0, + 0xc8, 0xb0, 0xcd, 0xb6, 0x75, 0xc6, 0x96, 0xce, 0x84, 0xc5, 0x93, 0xe2, 0xb1, 0xb9, + 0xe2, 0xb1, 0xa8, 0xc7, 0xb0, 0x45, 0xc5, 0x8b, 0x7a, 0xc3, 0x84, 0xc6, 0x80, 0xc7, + 0x9b, 0xc5, 0x9c, 0xc3, 0xa3, 0xc8, 0xba, 0xcd, 0xbc, 0xcd, 0xbd, 0xc8, 0xa7, 0xc4, + 0x8a, 0xc5, 0xa2, 0xe2, 0xb1, 0xb7, 0xc4, 0x84, 0xcd, 0xbe, 0xc7, 0xa1, 0xc4, 0xa3, + 0xc5, 0x9d, 0xc7, 0xad, 0xc8, 0xb6, 0xc7, 0xb5, 0xc5, 0x8e, 0xe1, 0x9a, 0xb6, 0x65, + 0xe2, 0xb1, 0xb7, 0xc6, 0xaf, 0xc9, 0x8d, 0xe1, 0x9a, 0xbe, 0xc7, 0x8b, 0x5c, 0x74, + 0xc8, 0x8a, 0xc8, 0x83, 0xc3, 0x87, 0xc3, 0x83, 0xc6, 0xba, 0xc8, 0xbf, 0xc4, 0x9b, + 0x3e, 0xc7, 0x96, 0xc7, 0x8b, 0xc5, 0x81, 0xcd, 0xb2, 0xc5, 0x8e, 0xc8, 0x8d, 0xc3, + 0xa1, 0x5f, 0xc5, 0xa9, 0xc2, 0xbb, 0xe1, 0x9a, 0xa6, 0xc9, 0x88, 0x5e, 0xc9, 0x85, + 0xc8, 0x91, 0xe1, 0x9b, 0x8e, 0xc4, 0x8f, 0xe1, 0x9b, 0xa4, 0xe1, 0x9a, 0xa8, 0xc6, + 0xa5, 0x77, 0xc3, 0x85, 0xc7, 0x97, 0xc3, 0xaf, 0xe1, 0x9a, 0xaf, 0x64, 0x6d, 0xc8, + 0xa3, 0xc3, 0x92, 0xe2, 0xb1, 0xbd, 0xc8, 0xb7, 0xe1, 0x9b, 0x86, 0xe2, 0xb1, 0xb9, + 0xc6, 0xa1, 0xc3, 0x82, 0xc7, 0x8b, 0xc7, 0x91, 0xc9, 0x86, 0xc5, 0x89, 0xe1, 0x9b, + 0xae, 0xc8, 0xb6, 0xc4, 0xbb, 0x57, 0xc3, 0xa6, 0xc2, 0xa3, 0xc5, 0xad, 0x2a, 0x6e, + 0xc3, 0x90, 0xc5, 0xa1, 0xc4, 0x87, 0xc2, 0xb7, 0xc5, 0xb1, 0xc4, 0x99, 0xc6, 0xbd, + 0xe1, 0x9b, 0x81, 0xe1, 0x9b, 0x8e, 0x28, 0xc8, 0xb6, 0xc2, 0xb5, 0xe1, 0x9a, 0xa6, + 0xc6, 0x83, 0xe1, 0x9a, 0xbe, 0xc6, 0xbf, 0x2f, 0xc3, 0x80, 0xe1, 0x9a, 0xa2, 0xc7, + 0xa2, 0xc5, 0xb1, 0xe1, 0x9b, 0x83, 0xe1, 0x9a, 0xa7, 0xc6, 0x85, 0xc7, 0x93, 0xc5, + 0x95, 0xc8, 0xaf, 0xc7, 0x97, 0x2e, 0xe2, 0xb1, 0xaf, 0xc8, 0xbf, 0xe1, 0x9b, 0x81, + 0xc3, 0xac, 0x4d, 0xc3, 0xa0, 0xc6, 0x97, 0xe1, 0x9b, 0x92, 0xe1, 0x9b, 0x9f, 0xc4, + 0x9d, 0xc8, 0x9b, 0xc6, 0xab, 0xc7, 0x92, 0xc6, 0x95, 0xc5, 0xbf, 0x6b, 0xc7, 0xa0, + 0x5a, 0xc3, 0x94, 0xc6, 0x96, 0xc4, 0x8e, 0xc6, 0xac, 0xc6, 0xb9, 0xc3, 0xb1, 0xc8, + 0xbd, 0xc8, 0x88, 0xc5, 0xb5, 0xc6, 0x9f, 0xc3, 0x9b, 0xc7, 0xae, 0xc5, 0x9c, 0xc4, + 0xb5, 0xc6, 0x9e, 0xc3, 0x99, 0xc2, 0xa9, 0xc6, 0xba, 0xc8, 0x9f, 0xc7, 0x83, 0xc8, + 0xbb, 0x34, 0xc3, 0xb5, 0xc5, 0x8a, 0x3b, 0xc2, 0xaa, 0x7b, 0xc4, 0x8c, 0xc3, 0xbb, + 0xc8, 0xb9, 0xc5, 0xb5, 0xce, 0x87, 0xc2, 0xb8, 0xc3, 0x97, 0xe1, 0x9b, 0x84, 0xc8, + 0x85, 0xc2, 0xa8, 0xc2, 0xab, 0xc8, 0x9a, 0xc6, 0xb2, 0xe2, 0xb1, 0xac, 0xc4, 0xa8, + 0xc4, 0xb2, 0xc9, 0x8b, 0xc5, 0xb4, 0xc6, 0x84, 0xc3, 0xb0, 0xc6, 0xb9, 0xe2, 0xb1, + 0xae, 0x5b, 0xc8, 0x8b, 0xc3, 0xaa, 0xc5, 0x82, 0xc5, 0xb6, 0xc8, 0x8d, 0xc9, 0x83, + 0xc5, 0x91, 0xc9, 0x8c, 0xc2, 0xab, 0xc6, 0x9d, + ], + asset_base: [ + 0xb2, 0x75, 0x51, 0xe5, 0x55, 0x32, 0x2a, 0x10, 0x94, 0x42, 0x4d, 0x4c, 0xe8, 0x6d, + 0xde, 0x6c, 0x6d, 0xf1, 0xbd, 0xec, 0xb6, 0x31, 0x5a, 0x6a, 0xa1, 0xc5, 0x58, 0xc9, + 0x82, 0x49, 0x54, 0x13, + ], + }, + TestVector { + key: [ + 0x0b, 0x08, 0x3c, 0x42, 0x29, 0xbd, 0x05, 0x85, 0xa4, 0xa0, 0xf5, 0xe8, 0x06, 0x55, + 0x2b, 0x65, 0xee, 0x24, 0xc7, 0x1a, 0x4a, 0x2a, 0x19, 0x7f, 0x9e, 0x85, 0x5e, 0xdc, + 0x2e, 0x1a, 0x09, 0xfa, + ], + description: [ + 0xc5, 0xa0, 0x2a, 0xc4, 0xbc, 0xc6, 0x92, 0xc6, 0x9b, 0xc6, 0x9f, 0xe1, 0x9b, 0xaf, + 0xe2, 0xb1, 0xb7, 0xc4, 0x9a, 0xc8, 0x93, 0xe1, 0x9b, 0x8d, 0x2b, 0xc3, 0x8b, 0xe2, + 0xb1, 0xa0, 0xc5, 0xa4, 0xc6, 0x9d, 0xc3, 0xb6, 0xc6, 0xb4, 0xc4, 0xb5, 0x68, 0xcd, + 0xba, 0xc6, 0x91, 0xc3, 0xa5, 0xc2, 0xaf, 0xe2, 0xb1, 0xbe, 0x6d, 0xc9, 0x86, 0xc6, + 0x8c, 0x30, 0xc6, 0x90, 0xc7, 0xb3, 0xe1, 0x9b, 0x96, 0x6e, 0xc5, 0xac, 0xe2, 0xb1, + 0xbc, 0x41, 0xc6, 0xb6, 0xc6, 0xab, 0xe2, 0xb1, 0xb0, 0xc7, 0xa6, 0xe1, 0x9a, 0xa1, + 0xc2, 0xaa, 0xe1, 0x9b, 0x8a, 0xc6, 0xa9, 0xc4, 0x91, 0xc4, 0xb8, 0xc2, 0xb7, 0xce, + 0x8c, 0xc3, 0x98, 0x76, 0xc4, 0x98, 0xc5, 0xa4, 0xc7, 0x9f, 0xc5, 0xb9, 0xc8, 0x96, + 0xe1, 0x9a, 0xbf, 0xce, 0x88, 0xc5, 0xaf, 0xc4, 0x94, 0xc3, 0x84, 0xc7, 0xa3, 0xc3, + 0x8c, 0xc7, 0x99, 0xcd, 0xb5, 0xc7, 0x9c, 0xc7, 0xb7, 0xe1, 0x9b, 0x96, 0xc9, 0x82, + 0xe1, 0x9a, 0xb0, 0xc6, 0x8b, 0xc6, 0x8f, 0xc7, 0x8c, 0x3c, 0x68, 0xc8, 0x8d, 0xc5, + 0x8e, 0xc3, 0xaf, 0xc6, 0x90, 0xe1, 0x9a, 0xa5, 0xe1, 0x9a, 0xbe, 0x26, 0xcd, 0xbb, + 0xc6, 0x80, 0xc5, 0x82, 0x34, 0xc3, 0x8a, 0x36, 0xc8, 0xa6, 0xcd, 0xbb, 0xe1, 0x9b, + 0xa1, 0xc8, 0xaa, 0xc3, 0x86, 0x65, 0xc3, 0xaa, 0xc8, 0xa3, 0xc7, 0xa7, 0xc7, 0xa9, + 0xc3, 0xbb, 0x61, 0xc3, 0xbe, 0xc5, 0xae, 0xc2, 0xb0, 0x6c, 0xc5, 0x9a, 0xc4, 0xbc, + 0xc8, 0xb6, 0xc4, 0x82, 0xc4, 0x89, 0xc6, 0x8d, 0xc5, 0x90, 0xc8, 0x86, 0xc6, 0x8a, + 0xc7, 0xac, 0xc8, 0x87, 0xe1, 0x9a, 0xb3, 0xc2, 0xa2, 0x33, 0xc8, 0x8b, 0x2b, 0xc8, + 0x99, 0xc7, 0xae, 0x4e, 0xc5, 0xa2, 0xc5, 0xaa, 0x7e, 0xc7, 0x9b, 0xc6, 0x9d, 0xc6, + 0xbe, 0xc8, 0xa8, 0xc6, 0xa9, 0xc4, 0xb0, 0xe1, 0x9b, 0xa9, 0xce, 0x89, 0x41, 0x7a, + 0xc8, 0xbd, 0xe1, 0x9b, 0xaf, 0xc4, 0x8d, 0xc7, 0x88, 0x40, 0xc5, 0x9c, 0xe1, 0x9b, + 0x9d, 0xc2, 0xac, 0xc9, 0x8d, 0x41, 0xc5, 0xae, 0xe1, 0x9b, 0x87, 0xc7, 0x92, 0xc4, + 0x98, 0xc6, 0x97, 0xc2, 0xab, 0x63, 0xce, 0x8c, 0xe1, 0x9b, 0x9d, 0xc2, 0xbc, 0xc4, + 0xae, 0xc4, 0x97, 0xc8, 0x91, 0xc5, 0xa6, 0x66, 0xc4, 0xb4, 0xc4, 0xb0, 0xe1, 0x9a, + 0xb0, 0x65, 0xc8, 0xb4, 0xc7, 0x8b, 0xe1, 0x9a, 0xa2, 0xc5, 0x98, 0xc8, 0xa5, 0xc4, + 0x9f, 0xce, 0x86, 0xc7, 0xa8, 0xc3, 0xaf, 0xc8, 0xa0, 0xc7, 0x96, 0xc4, 0xa3, 0xc4, + 0x84, 0xc4, 0x98, 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xb1, 0xc2, 0xa3, 0xe1, 0x9b, 0xa7, + 0xc8, 0x8f, 0xe1, 0x9a, 0xa9, 0xc5, 0xba, 0xc5, 0x8b, 0xe1, 0x9b, 0x97, 0xc8, 0xaa, + 0xc7, 0x93, 0xc2, 0xaa, 0xc7, 0x96, 0xc3, 0xb5, 0xc5, 0xb0, 0xc8, 0x81, 0xc8, 0x93, + 0xc2, 0xac, 0xc5, 0xa0, 0x3f, 0x5d, 0xc7, 0x97, 0x4a, 0xc7, 0x91, 0xc9, 0x80, 0xc6, + 0x94, 0xc4, 0xba, 0xc3, 0x96, 0x3c, 0xe1, 0x9b, 0x90, 0xc3, 0x8f, 0xc5, 0xb1, 0xc3, + 0xa8, 0xc4, 0xb6, 0xc6, 0x8e, 0xcd, 0xb6, 0xe1, 0x9b, 0x89, 0x26, 0xc7, 0x9f, 0xc6, + 0x8c, 0xc3, 0xb5, 0xe1, 0x9b, 0xad, 0xc8, 0x85, 0xc2, 0xb7, 0xc6, 0x96, 0xc3, 0x8a, + 0xe2, 0xb1, 0xab, 0xc8, 0x9a, 0x31, 0xc8, 0x81, 0xc7, 0xa9, 0x44, 0xc4, 0xb2, 0xe1, + 0x9a, 0xb1, 0xe2, 0xb1, 0xa9, 0xc3, 0xa8, 0x2f, 0xc7, 0xa3, 0xc5, 0x83, 0xc5, 0xb5, + 0xe2, 0xb1, 0xa5, 0xc5, 0xbb, 0xc8, 0x84, 0xc5, 0xbf, 0xc7, 0xb5, 0xc5, 0x80, 0xc2, + 0xbc, 0xc5, 0xba, 0x74, 0xc8, 0x92, 0xc4, 0x99, 0xc7, 0xbc, 0xc7, 0x9d, 0xc2, 0xba, + 0xc5, 0x91, 0x75, 0xc7, 0xbd, 0xe1, 0x9a, 0xb4, + ], + asset_base: [ + 0x97, 0xf4, 0x4c, 0x37, 0x3a, 0x55, 0x30, 0xbd, 0xc9, 0xd4, 0xbb, 0x76, 0x26, 0x65, + 0x03, 0xb4, 0xfd, 0x4a, 0x24, 0xf0, 0x22, 0x23, 0x13, 0xe4, 0xff, 0x45, 0x97, 0x74, + 0xa6, 0x9a, 0x4f, 0x34, + ], + }, + TestVector { + key: [ + 0x02, 0x66, 0x60, 0x55, 0xf4, 0x0b, 0x89, 0x61, 0x24, 0xe3, 0x67, 0x56, 0xa7, 0xa0, + 0x93, 0xbb, 0x8e, 0x0b, 0xaa, 0x26, 0x3c, 0xab, 0x79, 0x67, 0x3b, 0x0f, 0x3d, 0x09, + 0x74, 0x68, 0x8e, 0xa1, + ], + description: [ + 0xc7, 0xac, 0xc3, 0xa5, 0xc7, 0xa7, 0x62, 0xc3, 0xb5, 0x4d, 0xc6, 0x80, 0xc3, 0x83, + 0xe1, 0x9a, 0xa5, 0x3c, 0xc5, 0x84, 0xc8, 0x92, 0xc5, 0x8f, 0xc4, 0x95, 0xc8, 0x95, + 0xc3, 0xb4, 0xe1, 0x9b, 0x84, 0xc7, 0xa0, 0xc5, 0x83, 0xc9, 0x83, 0xe1, 0x9b, 0xb0, + 0xe2, 0xb1, 0xb6, 0xcd, 0xb1, 0xe1, 0x9a, 0xb2, 0xc7, 0x85, 0xc7, 0x8d, 0xe1, 0x9b, + 0x91, 0xc6, 0x9b, 0xc4, 0x8e, 0x63, 0xe1, 0x9a, 0xa7, 0x4c, 0xe1, 0x9b, 0xa0, 0xc6, + 0xb0, 0xe2, 0xb1, 0xb5, 0xc2, 0xa1, 0xe1, 0x9b, 0x93, 0xc3, 0xa1, 0xc6, 0xb5, 0x68, + 0xc5, 0xab, 0xc5, 0x8d, 0xc6, 0xb5, 0xc3, 0x8c, 0xce, 0x89, 0x4e, 0xc8, 0xb4, 0xc4, + 0xb4, 0xc2, 0xb0, 0xc8, 0x99, 0xc3, 0x86, 0xc4, 0x91, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, + 0x88, 0x61, 0xc6, 0x8a, 0xc6, 0xa7, 0xc7, 0x8c, 0x71, 0x76, 0xc6, 0xbc, 0xe1, 0x9b, + 0x9a, 0x77, 0xc5, 0x9c, 0xc8, 0xaa, 0xc3, 0x95, 0xc7, 0x9f, 0xce, 0x8c, 0xc3, 0xa5, + 0xc4, 0x96, 0xc3, 0x95, 0xc3, 0xa2, 0xe1, 0x9b, 0x98, 0xc2, 0xb4, 0xc7, 0xb1, 0xcd, + 0xb1, 0xc4, 0xbb, 0x2d, 0xc8, 0xa8, 0xe1, 0x9a, 0xab, 0xc7, 0x8f, 0xc4, 0x83, 0xe1, + 0x9b, 0xa8, 0xc5, 0x93, 0xc8, 0x97, 0xe1, 0x9a, 0xa3, 0xc3, 0x81, 0xc3, 0x8a, 0x37, + 0xc4, 0xa9, 0xc2, 0xb8, 0x2b, 0xc8, 0xbb, 0xc7, 0x91, 0xe1, 0x9a, 0xb7, 0xc7, 0xa3, + 0x6c, 0xe1, 0x9b, 0x96, 0xc8, 0xbf, 0xc8, 0xaf, 0xc4, 0x98, 0xc9, 0x8e, 0xc8, 0x9e, + 0xc2, 0xb9, 0xc7, 0x80, 0xc3, 0xb2, 0xc3, 0xb0, 0xc3, 0xa1, 0xc5, 0xaf, 0xc5, 0x83, + 0xc4, 0x87, 0xe2, 0xb1, 0xbb, 0x4f, 0xc8, 0xa9, 0xc6, 0x9f, 0xc9, 0x8b, 0x67, 0xcd, + 0xb4, 0x5a, 0xc2, 0xa7, 0xe2, 0xb1, 0xa6, 0xc5, 0x8c, 0xc3, 0x8f, 0xc6, 0x8b, 0xc7, + 0x9c, 0xc9, 0x8a, 0xe2, 0xb1, 0xaa, 0xe2, 0xb1, 0xb0, 0xc8, 0xb7, 0xc4, 0x9e, 0xc6, + 0xbd, 0xc2, 0xb0, 0xc5, 0x91, 0xc6, 0xbb, 0xc5, 0xbb, 0xc6, 0xa0, 0xc3, 0xa8, 0xc2, + 0xa5, 0xc8, 0xb0, 0xc4, 0x91, 0xc2, 0xa9, 0xc2, 0xab, 0xc8, 0x99, 0xe1, 0x9a, 0xa4, + 0xc5, 0x87, 0xe1, 0x9a, 0xa2, 0xc7, 0xa6, 0x37, 0x73, 0xc8, 0x8b, 0x74, 0xc5, 0xab, + 0xc3, 0x85, 0xe1, 0x9b, 0x9c, 0xc6, 0x87, 0xc5, 0x82, 0xc4, 0xa9, 0xc8, 0x9b, 0xe2, + 0xb1, 0xb2, 0x6f, 0x51, 0x75, 0xc3, 0xab, 0xc2, 0xbd, 0x49, 0xc4, 0x97, 0x5e, 0xc8, + 0xb6, 0x5b, 0xc5, 0x9f, 0xc4, 0x98, 0xc8, 0x8f, 0x3a, 0xc6, 0x95, 0xc7, 0x8b, 0xc5, + 0x89, 0x3f, 0xc5, 0x9f, 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xb1, 0xc7, 0x84, 0xc4, 0xa6, + 0xe2, 0xb1, 0xa8, 0xc3, 0x85, 0xc3, 0xa5, 0xc8, 0x98, 0xc8, 0xa0, 0x5b, 0xc6, 0xba, + 0xe1, 0x9a, 0xa6, 0xc4, 0xad, 0xe2, 0xb1, 0xab, 0xc7, 0xa1, 0xe2, 0xb1, 0xbf, 0xe1, + 0x9b, 0xa8, 0x4c, 0xc4, 0x8f, 0x6a, 0xc5, 0x9d, 0xe1, 0x9b, 0xa8, 0xc6, 0xb5, 0xc8, + 0x8b, 0xce, 0x8c, 0xc7, 0xa2, 0xc6, 0xbd, 0x33, 0xc4, 0xb0, 0xe1, 0x9a, 0xb2, 0xc7, + 0x9d, 0xe2, 0xb1, 0xa5, 0xc2, 0xba, 0xc3, 0x8e, 0xc4, 0xbf, 0xc3, 0x9b, 0xc5, 0xad, + 0x73, 0xe1, 0x9a, 0xa6, 0x31, 0xc8, 0x93, 0xc9, 0x84, 0xc6, 0x84, 0xc2, 0xa9, 0xc2, + 0xa5, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, 0xb0, 0xc3, 0x97, 0x4f, 0x6b, 0x48, 0xc3, 0xb2, + 0xe1, 0x9a, 0xb5, 0xc5, 0x8a, 0xc5, 0x92, 0xe1, 0x9b, 0x8d, 0xc7, 0x8d, 0xc4, 0xa6, + 0x26, 0xc3, 0xab, 0xc4, 0x95, 0xc3, 0xb4, 0xc7, 0x9f, 0xc8, 0xa6, 0xc7, 0xaa, 0xc6, + 0xb5, 0xc5, 0x8c, 0x66, 0xc9, 0x82, 0xc7, 0x8a, 0xc7, 0x92, 0xc9, 0x88, 0xc4, 0x84, + 0xe2, 0xb1, 0xb3, 0x47, 0xc6, 0xbb, 0xc8, 0x83, + ], + asset_base: [ + 0xe7, 0x25, 0x94, 0x56, 0x3c, 0xb3, 0x92, 0xab, 0xbe, 0x95, 0x61, 0x61, 0xfa, 0xed, + 0x3d, 0x8d, 0xc4, 0xa1, 0xa0, 0x4e, 0x7c, 0x0d, 0x6e, 0x5b, 0xb8, 0x7d, 0x6c, 0xba, + 0x68, 0xc4, 0x45, 0x27, + ], + }, + TestVector { + key: [ + 0x0a, 0xc2, 0x8d, 0x35, 0x85, 0x55, 0x65, 0x95, 0xac, 0x16, 0x8a, 0x8c, 0xa3, 0xa0, + 0x63, 0x31, 0x9c, 0xdf, 0xbb, 0x4f, 0xaf, 0x2c, 0xa2, 0x48, 0x1d, 0x4d, 0xaa, 0x04, + 0x2d, 0x7c, 0xad, 0xa5, + ], + description: [ + 0xe2, 0xb1, 0xb0, 0xc6, 0x87, 0xc7, 0xb8, 0x58, 0xc8, 0x93, 0xe1, 0x9a, 0xb6, 0xc5, + 0xbf, 0xc3, 0xb0, 0xc5, 0x92, 0xc3, 0x83, 0x25, 0xc2, 0xb4, 0xc6, 0xbd, 0xc6, 0x87, + 0xe1, 0x9b, 0x81, 0xc4, 0x9e, 0xc6, 0x9c, 0xe1, 0x9b, 0x84, 0x46, 0x56, 0xe2, 0xb1, + 0xa4, 0xc3, 0xa9, 0xc5, 0xab, 0xe1, 0x9a, 0xbb, 0x55, 0xc4, 0x85, 0xc4, 0xa8, 0xc2, + 0xb1, 0xc8, 0xa4, 0xc3, 0xa4, 0x7e, 0xc4, 0x92, 0xc7, 0x9b, 0xc2, 0xac, 0xc3, 0xa1, + 0xc4, 0x81, 0xcd, 0xb2, 0xc2, 0xa6, 0xc2, 0xa1, 0xc3, 0xa2, 0xe1, 0x9b, 0x95, 0xc5, + 0xa4, 0xc7, 0xb5, 0xc8, 0x9f, 0xc9, 0x83, 0xe1, 0x9a, 0xa2, 0xc5, 0xb5, 0x25, 0xc5, + 0x9d, 0xc3, 0xb1, 0x5f, 0xc5, 0xa8, 0x69, 0xe1, 0x9b, 0x88, 0xc4, 0xb2, 0xe2, 0xb1, + 0xa8, 0xc8, 0xb8, 0x54, 0x4f, 0x2c, 0x6a, 0xc5, 0xbc, 0xc7, 0x84, 0xc8, 0x9b, 0xc6, + 0x89, 0xc5, 0x9a, 0xc5, 0xb1, 0xc7, 0x8e, 0xc6, 0xab, 0xc6, 0xbe, 0xc6, 0xae, 0xc8, + 0x8b, 0xc6, 0xbd, 0xc2, 0xa7, 0xc6, 0x9b, 0xc3, 0xb5, 0xc5, 0x8e, 0xc6, 0x92, 0xc8, + 0xaa, 0xc3, 0xb3, 0xc7, 0xbf, 0xc2, 0xb4, 0xc3, 0xa6, 0xc7, 0xb7, 0xc7, 0x9a, 0xc3, + 0xb1, 0xc2, 0xa7, 0xc4, 0xb8, 0xc6, 0x93, 0xc7, 0xae, 0xc6, 0x8c, 0x74, 0x5c, 0xc6, + 0xa1, 0x42, 0x4c, 0xc6, 0xb6, 0xc9, 0x8a, 0x50, 0xc8, 0xba, 0xc7, 0xa5, 0xc8, 0x9d, + 0xc8, 0x9b, 0xc5, 0xa0, 0xc7, 0x99, 0x21, 0x5e, 0x24, 0xc6, 0x93, 0xc6, 0x9b, 0xc7, + 0x8d, 0xc8, 0x9b, 0xe1, 0x9b, 0x93, 0xc6, 0x8f, 0xc4, 0xb6, 0xe1, 0x9a, 0xa5, 0x45, + 0xe1, 0x9b, 0x8e, 0xc6, 0xbe, 0xe1, 0x9b, 0x9e, 0xc6, 0xa8, 0xe1, 0x9a, 0xa7, 0xc4, + 0xa6, 0xc5, 0x84, 0xc6, 0xbb, 0xc8, 0xad, 0xcd, 0xb2, 0xc6, 0xb8, 0x37, 0xc6, 0xb0, + 0xe1, 0x9b, 0x84, 0xc3, 0x84, 0xc8, 0x80, 0xc4, 0xb5, 0xc6, 0x91, 0xe2, 0xb1, 0xa5, + 0xc7, 0x83, 0x60, 0xc5, 0x8f, 0xc5, 0xb0, 0xc7, 0xa0, 0xc8, 0x96, 0xc2, 0xb2, 0xc8, + 0xa7, 0xc6, 0x9f, 0x2d, 0xc6, 0x99, 0xc5, 0xb8, 0xe1, 0x9a, 0xa6, 0xc7, 0x9b, 0xc6, + 0x9b, 0xc7, 0x99, 0xc3, 0x84, 0x3c, 0xc6, 0x9a, 0x52, 0xc3, 0xb0, 0xc5, 0xb7, 0xc2, + 0xab, 0x56, 0xc3, 0x91, 0xc8, 0xbe, 0xc5, 0x84, 0xc8, 0x84, 0xc5, 0xb9, 0xc7, 0xac, + 0xc8, 0x86, 0xc5, 0xa0, 0xc2, 0xb0, 0xc3, 0xa7, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x84, + 0xe1, 0x9b, 0x89, 0xc8, 0x80, 0xc6, 0x82, 0xc5, 0xb1, 0x73, 0xc6, 0x84, 0xc4, 0xb1, + 0xc8, 0x8b, 0xc4, 0xab, 0xc3, 0xa5, 0xc5, 0xbb, 0xe1, 0x9b, 0x84, 0x63, 0xc3, 0xac, + 0xc3, 0xad, 0xc3, 0xb8, 0xc5, 0xac, 0xc8, 0x8f, 0xc7, 0xb0, 0xc4, 0x9d, 0xe1, 0x9a, + 0xac, 0xc6, 0x86, 0x7d, 0xe1, 0x9a, 0xbe, 0xc8, 0xac, 0xcd, 0xbc, 0xcd, 0xba, 0xce, + 0x8c, 0xc5, 0x9e, 0x57, 0xc4, 0x83, 0xc8, 0x96, 0xc5, 0xb5, 0xe2, 0xb1, 0xac, 0xc4, + 0xa6, 0xc8, 0xaf, 0xc8, 0x84, 0x65, 0xc5, 0x85, 0x5d, 0xc4, 0xb0, 0xc5, 0xbe, 0xc5, + 0x9b, 0x3d, 0xc7, 0x80, 0xe1, 0x9b, 0x81, 0xc6, 0x94, 0xc4, 0xb3, 0xe1, 0x9b, 0xa7, + 0xe2, 0xb1, 0xa2, 0x3d, 0xc5, 0x82, 0x4e, 0x44, 0xe1, 0x9a, 0xb5, 0xc6, 0x90, 0xc3, + 0x85, 0xe1, 0x9b, 0x82, 0xe1, 0x9a, 0xb3, 0xc7, 0xa2, 0xc5, 0x93, 0xc6, 0xa9, 0xc5, + 0x92, 0xc6, 0xb3, 0xce, 0x84, 0xe1, 0x9b, 0x87, 0xe1, 0x9b, 0x97, 0xe1, 0x9b, 0x9e, + 0xc6, 0x81, 0xc4, 0xb7, 0xe1, 0x9b, 0x9e, 0x3d, 0xc7, 0xb8, 0xe1, 0x9b, 0x97, 0xe1, + 0x9b, 0x9f, 0xc4, 0x81, 0xc5, 0x8a, 0x2c, 0xc6, 0x9a, 0x21, 0xc4, 0xb8, 0xc4, 0xa9, + 0xc2, 0xa9, 0xc5, 0x89, 0xc8, 0xb5, 0x5a, 0x5a, + ], + asset_base: [ + 0x0b, 0xcf, 0xbd, 0x87, 0x2f, 0xc5, 0xed, 0x4c, 0x82, 0x80, 0x35, 0x16, 0x69, 0x20, + 0x77, 0x21, 0xc6, 0xd2, 0x15, 0x67, 0xdd, 0x34, 0x10, 0x5c, 0x89, 0x7d, 0xbf, 0x66, + 0x19, 0x95, 0xa3, 0x1d, + ], + }, + ] +} diff --git a/src/test_vectors/issuance_auth_sig.rs b/src/test_vectors/issuance_auth_sig.rs new file mode 100644 index 000000000..648a5cfb4 --- /dev/null +++ b/src/test_vectors/issuance_auth_sig.rs @@ -0,0 +1,277 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_issuance_auth_sig) + +pub(crate) struct TestVector { + pub(crate) isk: [u8; 32], + pub(crate) ik: [u8; 32], + pub(crate) msg: [u8; 32], + pub(crate) sig: [u8; 64], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + isk: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, + ], + ik: [ + 0xf9, 0x30, 0x8a, 0x01, 0x92, 0x58, 0xc3, 0x10, 0x49, 0x34, 0x4f, 0x85, 0xf8, 0x9d, + 0x52, 0x29, 0xb5, 0x31, 0xc8, 0x45, 0x83, 0x6f, 0x99, 0xb0, 0x86, 0x01, 0xf1, 0x13, + 0xbc, 0xe0, 0x36, 0xf9, + ], + msg: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + sig: [ + 0xe9, 0x07, 0x83, 0x1f, 0x80, 0x84, 0x8d, 0x10, 0x69, 0xa5, 0x37, 0x1b, 0x40, 0x24, + 0x10, 0x36, 0x4b, 0xdf, 0x1c, 0x5f, 0x83, 0x07, 0xb0, 0x08, 0x4c, 0x55, 0xf1, 0xce, + 0x2d, 0xca, 0x82, 0x15, 0x25, 0xf6, 0x6a, 0x4a, 0x85, 0xea, 0x8b, 0x71, 0xe4, 0x82, + 0xa7, 0x4f, 0x38, 0x2d, 0x2c, 0xe5, 0xeb, 0xee, 0xe8, 0xfd, 0xb2, 0x17, 0x2f, 0x47, + 0x7d, 0xf4, 0x90, 0x0d, 0x31, 0x05, 0x36, 0xc0, + ], + }, + TestVector { + isk: [ + 0x5d, 0x7a, 0x8f, 0x73, 0x9a, 0x2d, 0x9e, 0x94, 0x5b, 0x0c, 0xe1, 0x52, 0xa8, 0x04, + 0x9e, 0x29, 0x4c, 0x4d, 0x6e, 0x66, 0xb1, 0x64, 0x93, 0x9d, 0xaf, 0xfa, 0x2e, 0xf6, + 0xee, 0x69, 0x21, 0x48, + ], + ik: [ + 0x4b, 0xec, 0xe1, 0xff, 0x00, 0xe2, 0xed, 0x77, 0x64, 0xae, 0x6b, 0xe2, 0x0d, 0x2f, + 0x67, 0x22, 0x04, 0xfc, 0x86, 0xcc, 0xed, 0xd6, 0xfc, 0x1f, 0x71, 0xdf, 0x02, 0xc7, + 0x51, 0x6d, 0x9f, 0x31, + ], + msg: [ + 0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0xd9, 0x61, 0x4f, 0xc8, 0x20, 0x90, 0x5d, + 0x04, 0x2b, 0xb1, 0xef, 0x9c, 0xa3, 0xf2, 0x49, 0x88, 0xc7, 0xb3, 0x53, 0x42, 0x01, + 0xcf, 0xb1, 0xcd, 0x8d, + ], + sig: [ + 0xa5, 0xb5, 0x92, 0x78, 0x1b, 0xeb, 0x55, 0xee, 0xbf, 0x8b, 0xc2, 0xbf, 0xd7, 0x9d, + 0xa9, 0x45, 0x2d, 0xc9, 0x22, 0x39, 0x87, 0x7e, 0xb7, 0xe1, 0xf5, 0x64, 0x65, 0xff, + 0x11, 0x1e, 0x59, 0x08, 0xde, 0xac, 0x15, 0xd5, 0x69, 0x99, 0x9a, 0x2b, 0xd2, 0x2b, + 0x2e, 0xf6, 0x01, 0xc5, 0x81, 0x3b, 0xdb, 0xba, 0x99, 0x3c, 0x08, 0xd4, 0xe8, 0x56, + 0xc9, 0x26, 0xd9, 0xe2, 0xc0, 0x63, 0x93, 0x67, + ], + }, + TestVector { + isk: [ + 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, + 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, + 0x30, 0xa7, 0x35, 0x94, + ], + ik: [ + 0xd4, 0x22, 0x9e, 0x19, 0x5e, 0x25, 0xf6, 0x02, 0xa2, 0x18, 0x61, 0x22, 0xcb, 0x4e, + 0x78, 0x76, 0x7b, 0x3c, 0x66, 0xac, 0x39, 0x08, 0x08, 0xd2, 0xd1, 0xb4, 0x04, 0x42, + 0xda, 0x7f, 0x00, 0x66, + ], + msg: [ + 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, 0x25, + 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, 0x91, + 0x2a, 0x63, 0x81, 0xce, + ], + sig: [ + 0x18, 0x8b, 0x15, 0x57, 0x42, 0x87, 0x83, 0x55, 0x6b, 0x66, 0x80, 0x3b, 0xf9, 0x06, + 0x63, 0xb7, 0xa1, 0x6d, 0x43, 0x76, 0x92, 0x7c, 0x58, 0x35, 0xe0, 0xb7, 0x26, 0x52, + 0x0e, 0xb2, 0x6d, 0x53, 0x24, 0x99, 0x10, 0xc3, 0x9c, 0x5f, 0x05, 0x90, 0xb6, 0xd6, + 0xaa, 0xb3, 0x51, 0xff, 0x8c, 0xd8, 0xe0, 0x63, 0xfa, 0x74, 0x20, 0x42, 0x55, 0xda, + 0xdc, 0x00, 0xd9, 0xe0, 0xdf, 0xf7, 0x7b, 0x09, + ], + }, + TestVector { + isk: [ + 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, 0xd7, 0x55, 0x1d, 0xb5, 0xfd, + 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, 0xd4, 0x77, 0x08, 0x37, 0x56, + 0xd5, 0x9a, 0xf8, 0x0d, + ], + ik: [ + 0xce, 0xb7, 0x5a, 0x43, 0x9f, 0xf0, 0x16, 0x15, 0x80, 0xbf, 0x29, 0x57, 0x24, 0xc6, + 0xd9, 0x2d, 0x31, 0xb7, 0xaa, 0x02, 0x84, 0x03, 0x39, 0x44, 0x49, 0x64, 0x48, 0x6f, + 0xae, 0xa8, 0x90, 0xe5, + ], + msg: [ + 0x06, 0xa7, 0x45, 0xf4, 0x4a, 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, + 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, + 0xcc, 0xb8, 0xf6, 0x76, + ], + sig: [ + 0x6e, 0x5e, 0xd6, 0x65, 0x6c, 0x32, 0x71, 0x32, 0xb1, 0x65, 0x81, 0x06, 0x2f, 0x1b, + 0x13, 0x8a, 0xcc, 0x6f, 0x1f, 0x83, 0x43, 0xed, 0x9d, 0x89, 0xab, 0x5f, 0xd9, 0x38, + 0xe4, 0xe6, 0xce, 0xf7, 0x99, 0xa2, 0x25, 0x1c, 0xa5, 0x2d, 0x60, 0x82, 0x0e, 0x51, + 0x00, 0x25, 0x06, 0x7d, 0xcd, 0x1b, 0xf7, 0x54, 0xc5, 0xbf, 0xf1, 0x39, 0xb4, 0xcc, + 0x44, 0xb3, 0x7d, 0x27, 0xd1, 0x7c, 0x4a, 0xee, + ], + }, + TestVector { + isk: [ + 0x49, 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, + 0xc2, 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, + 0x94, 0x90, 0x3d, 0x3c, + ], + ik: [ + 0xb0, 0xfa, 0x9d, 0x77, 0xfc, 0xbd, 0x96, 0x45, 0x91, 0x32, 0xe3, 0x05, 0xe3, 0x24, + 0xe7, 0x93, 0x6a, 0xe1, 0x3b, 0x15, 0x14, 0x7e, 0x20, 0x5d, 0x7b, 0xae, 0x42, 0xfa, + 0x7f, 0xaf, 0x5d, 0x1e, + ], + msg: [ + 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, + 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, + 0xe3, 0x4a, 0x98, 0x51, + ], + sig: [ + 0x17, 0xc2, 0xe5, 0xdf, 0x2e, 0xa6, 0xa1, 0x2e, 0x8a, 0xb2, 0xb0, 0xd5, 0x04, 0x89, + 0x8f, 0x3f, 0x23, 0x43, 0xe0, 0x98, 0x90, 0x7f, 0x7a, 0xfe, 0x43, 0xac, 0x8a, 0x01, + 0x14, 0x42, 0x35, 0x80, 0x97, 0x53, 0x67, 0xba, 0x4b, 0x6d, 0x16, 0x6c, 0x44, 0x28, + 0x48, 0x57, 0xb7, 0xcd, 0x29, 0xa8, 0x38, 0xb4, 0x9c, 0xc3, 0x41, 0xd2, 0x89, 0x51, + 0xaa, 0x0b, 0x5d, 0x55, 0x6a, 0x20, 0x9e, 0xb6, + ], + }, + TestVector { + isk: [ + 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, + 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, + 0x32, 0x0d, 0xad, 0xd6, + ], + ik: [ + 0x0b, 0xb4, 0x91, 0x3d, 0xba, 0xf1, 0x4e, 0xf6, 0xd0, 0xad, 0xeb, 0x8b, 0x70, 0x27, + 0xbf, 0x0b, 0x9a, 0x8f, 0x59, 0x0d, 0x3e, 0x2d, 0x95, 0xa1, 0x2d, 0xba, 0xaf, 0x0b, + 0x95, 0x33, 0xdc, 0xa4, + ], + msg: [ + 0x4f, 0x54, 0x31, 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, + 0x13, 0x09, 0x13, 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, + 0x47, 0xf1, 0xe1, 0x91, + ], + sig: [ + 0x42, 0x1f, 0x5b, 0x07, 0x57, 0x2e, 0x6b, 0x05, 0xe8, 0x0b, 0xa5, 0x85, 0xff, 0x63, + 0x21, 0x42, 0x26, 0x75, 0xcd, 0x19, 0xea, 0x59, 0x15, 0xd6, 0x32, 0xeb, 0x47, 0x64, + 0x6c, 0xe2, 0x20, 0x27, 0x6b, 0xb7, 0x82, 0x42, 0xcc, 0x75, 0x48, 0xd9, 0xa0, 0x57, + 0x2b, 0x89, 0x69, 0x2e, 0x5b, 0x95, 0xdb, 0x14, 0x14, 0xe4, 0xeb, 0xd2, 0x20, 0xcc, + 0xf8, 0x3a, 0xf2, 0x98, 0x2f, 0xdd, 0x3a, 0xec, + ], + }, + TestVector { + isk: [ + 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, 0xa9, + 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, 0xda, + 0xe6, 0x9c, 0xe8, 0xfc, + ], + ik: [ + 0x61, 0xbb, 0x33, 0x91, 0x59, 0xdf, 0x98, 0x20, 0xef, 0xae, 0xb6, 0x1d, 0x9a, 0x10, + 0xcd, 0xc1, 0x3b, 0x4c, 0x99, 0xfd, 0xc8, 0x6d, 0x94, 0x85, 0x11, 0x5d, 0xfd, 0x83, + 0x62, 0x36, 0xac, 0xf8, + ], + msg: [ + 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, 0x93, 0x1d, 0xe5, 0x18, 0x85, + 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, 0xc9, 0x37, 0x83, 0x65, 0xc8, + 0xf7, 0x39, 0x3c, 0x94, + ], + sig: [ + 0x5a, 0x11, 0x48, 0xa8, 0x92, 0x8f, 0xbf, 0x43, 0xbb, 0x33, 0xa5, 0x70, 0xf0, 0xdf, + 0xa3, 0x53, 0x32, 0xb7, 0x01, 0x80, 0x21, 0xa0, 0xcb, 0x75, 0xe9, 0x55, 0x4e, 0x86, + 0xec, 0xb2, 0x1d, 0xa3, 0x2e, 0xb5, 0xa2, 0xd8, 0xc5, 0x9e, 0xa3, 0x90, 0x43, 0xb9, + 0x74, 0x78, 0x75, 0x0c, 0x6b, 0xf8, 0x66, 0xeb, 0x3b, 0x01, 0x5e, 0xbb, 0x31, 0x68, + 0xf7, 0x53, 0x76, 0x6a, 0xd1, 0x71, 0xd2, 0x1e, + ], + }, + TestVector { + isk: [ + 0xe2, 0x88, 0x53, 0x15, 0xeb, 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, + 0xe5, 0x3e, 0x29, 0xfe, 0xf2, 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, + 0xf4, 0x68, 0xa0, 0x08, + ], + ik: [ + 0x19, 0x58, 0x53, 0x8b, 0x12, 0x17, 0xa0, 0x3d, 0x89, 0xcd, 0x83, 0xb8, 0x3d, 0x0b, + 0xdd, 0x40, 0xa6, 0x9a, 0xbe, 0x3a, 0xc2, 0x5d, 0x00, 0xc6, 0xd2, 0x69, 0x97, 0xf9, + 0xf2, 0x57, 0x4d, 0x4f, + ], + msg: [ + 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, + 0x3f, 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, + 0x03, 0x59, 0x65, 0x55, + ], + sig: [ + 0x16, 0x90, 0xf5, 0x43, 0xee, 0x67, 0xbb, 0x1c, 0xe0, 0xe4, 0x25, 0x4e, 0xa5, 0xdf, + 0xd0, 0x42, 0xfe, 0x86, 0x3a, 0xb4, 0x6c, 0xd9, 0xa8, 0x90, 0x55, 0x19, 0xff, 0xb1, + 0xb8, 0x40, 0x6b, 0xec, 0xbd, 0x90, 0xda, 0x66, 0xe5, 0xb5, 0x44, 0xbc, 0xd4, 0x3b, + 0xdb, 0x29, 0xbc, 0x5d, 0x2c, 0x02, 0x4d, 0xd2, 0x85, 0xab, 0xcd, 0x77, 0xe4, 0xac, + 0x1f, 0x9d, 0x60, 0x35, 0x22, 0xe4, 0xf1, 0x5b, + ], + }, + TestVector { + isk: [ + 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, 0x89, 0x26, + 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, + 0x99, 0x58, 0x9c, 0x8b, + ], + ik: [ + 0x7d, 0xd6, 0xd7, 0x61, 0xe1, 0x02, 0x01, 0x37, 0xfa, 0x01, 0xb4, 0xdd, 0xd3, 0xb0, + 0xf3, 0x48, 0x04, 0xcc, 0x10, 0xcc, 0x4e, 0x9f, 0x6e, 0x9d, 0xf5, 0xb6, 0x04, 0x69, + 0xf5, 0x79, 0x36, 0x67, + ], + msg: [ + 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, + 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, + 0xed, 0x42, 0x43, 0x5e, + ], + sig: [ + 0x59, 0x34, 0x5d, 0x6b, 0x89, 0x4e, 0xd6, 0xd0, 0x3a, 0x56, 0x73, 0xa0, 0x14, 0x63, + 0x07, 0x51, 0x04, 0x3d, 0x11, 0xfa, 0x63, 0x18, 0x7c, 0x92, 0x9c, 0xae, 0x3f, 0xa1, + 0xb0, 0x29, 0x22, 0xf2, 0x7d, 0xc0, 0x16, 0x40, 0x33, 0x95, 0x2c, 0x84, 0x16, 0xe6, + 0xd0, 0x43, 0x81, 0x77, 0xb3, 0xbc, 0xe8, 0x78, 0xfd, 0xec, 0x75, 0x0a, 0x16, 0x64, + 0xd4, 0x89, 0xdf, 0x0a, 0x4e, 0xae, 0xb1, 0x35, + ], + }, + TestVector { + isk: [ + 0x92, 0x47, 0x69, 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, + 0x7b, 0x89, 0xe0, 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, + 0xf2, 0x65, 0x72, 0x50, + ], + ik: [ + 0xb5, 0x9c, 0x5f, 0x32, 0x34, 0xd6, 0xca, 0x36, 0xcc, 0x48, 0x3d, 0x67, 0xa8, 0x4f, + 0x37, 0xd6, 0xb2, 0x4b, 0x24, 0x45, 0x48, 0x25, 0xd2, 0xb7, 0xbf, 0xdc, 0x80, 0x2b, + 0x2e, 0x32, 0x8c, 0x43, + ], + msg: [ + 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc, + 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, 0xe7, + 0x1a, 0x02, 0xaf, 0x11, + ], + sig: [ + 0xa4, 0x58, 0x79, 0x33, 0x26, 0x98, 0x37, 0x74, 0x09, 0x6d, 0x36, 0x59, 0xeb, 0x9a, + 0x21, 0xd1, 0x2c, 0x8e, 0xb8, 0x77, 0x56, 0x6b, 0x66, 0xbf, 0x60, 0x33, 0xdb, 0x8f, + 0xde, 0x20, 0xc4, 0x66, 0xa2, 0xe9, 0x54, 0x30, 0xa0, 0x1e, 0xb9, 0xad, 0x28, 0xe0, + 0x76, 0x5b, 0xed, 0x21, 0xdc, 0xd3, 0x03, 0x86, 0xfc, 0xe7, 0xaa, 0xba, 0xde, 0xa6, + 0xda, 0x72, 0x8c, 0x16, 0xbb, 0x80, 0xf1, 0xc2, + ], + }, + TestVector { + isk: [ + 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, 0xb1, 0xfc, 0xe4, 0x67, 0x50, + 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, 0xc3, 0x82, 0x85, 0x7d, 0xee, + 0xcc, 0x40, 0xa9, 0x8d, + ], + ik: [ + 0x45, 0x61, 0x9f, 0x20, 0x6c, 0x3b, 0xfc, 0x84, 0xfd, 0x42, 0x4f, 0xfb, 0x5c, 0x81, + 0x6f, 0x65, 0x4b, 0x27, 0xaa, 0x7f, 0x7b, 0x4b, 0xd6, 0x7e, 0xc5, 0xf9, 0xac, 0x6d, + 0x0f, 0x38, 0xdb, 0xb1, + ], + msg: [ + 0x5f, 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0x2d, 0xd2, 0x1a, 0xfd, 0xbb, 0x5d, 0x47, + 0xfa, 0x9a, 0x6d, 0xd9, 0x84, 0xd5, 0x67, 0xdb, 0x28, 0x57, 0xb9, 0x27, 0xb7, 0xfa, + 0xe2, 0xdb, 0x58, 0x71, + ], + sig: [ + 0xe6, 0x92, 0x4d, 0x53, 0xec, 0x97, 0x80, 0x79, 0xd6, 0x6a, 0x28, 0x4c, 0x00, 0xa8, + 0x68, 0xf9, 0xeb, 0x75, 0x1a, 0xe3, 0xb1, 0x69, 0x0d, 0x15, 0xee, 0x1b, 0x39, 0x68, + 0x0b, 0x83, 0xc4, 0x38, 0xe4, 0x5f, 0x02, 0xa2, 0x3c, 0x65, 0x6e, 0x4e, 0x53, 0xd3, + 0xc7, 0x3e, 0xfa, 0x0d, 0xc5, 0xf7, 0xad, 0x63, 0x28, 0x21, 0x7f, 0xd5, 0x9b, 0x23, + 0xaa, 0xe4, 0xf9, 0x0c, 0x68, 0xbe, 0x76, 0xbc, + ], + }, + ] +} diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 39d7dc00d..0213eec1d 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -1,9 +1,11 @@ -//! Test vectors for Orchard key components. +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_key_components) pub(crate) struct TestVector { pub(crate) sk: [u8; 32], pub(crate) ask: [u8; 32], pub(crate) ak: [u8; 32], + pub(crate) isk: [u8; 32], + pub(crate) ik: [u8; 32], pub(crate) nk: [u8; 32], pub(crate) rivk: [u8; 32], pub(crate) ivk: [u8; 32], @@ -15,6 +17,7 @@ pub(crate) struct TestVector { pub(crate) internal_ivk: [u8; 32], pub(crate) internal_ovk: [u8; 32], pub(crate) internal_dk: [u8; 32], + pub(crate) asset: [u8; 32], pub(crate) note_v: u64, pub(crate) note_rho: [u8; 32], pub(crate) note_rseed: [u8; 32], @@ -23,7 +26,6 @@ pub(crate) struct TestVector { } pub(crate) fn test_vectors() -> Vec { - // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_key_components.py vec![ TestVector { sk: [ @@ -41,6 +43,16 @@ pub(crate) fn test_vectors() -> Vec { 0x12, 0x8b, 0x9a, 0x14, 0x0d, 0x5e, 0x07, 0xc1, 0x51, 0x72, 0x1d, 0xc1, 0x6d, 0x25, 0xd4, 0xe2, 0x0f, 0x15, ], + isk: [ + 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, + 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, + 0x99, 0x0e, 0xd8, 0x3d, + ], + ik: [ + 0xd1, 0xa2, 0xfa, 0xb4, 0x17, 0x0c, 0x45, 0xc5, 0xf9, 0x79, 0xc8, 0xe7, 0x46, 0x3b, + 0x8e, 0x20, 0xf2, 0x34, 0xde, 0x35, 0xeb, 0x58, 0xa8, 0x38, 0xdf, 0x9a, 0x1f, 0xe9, + 0xb1, 0xa5, 0xaa, 0x45, + ], nk: [ 0x9f, 0x2f, 0x82, 0x67, 0x38, 0x94, 0x5a, 0xd0, 0x1f, 0x47, 0xf7, 0x0d, 0xb0, 0xc3, 0x67, 0xc2, 0x46, 0xc2, 0x0c, 0x61, 0xff, 0x55, 0x83, 0x94, 0x8c, 0x39, 0xde, 0xa9, @@ -94,6 +106,11 @@ pub(crate) fn test_vectors() -> Vec { 0xfc, 0x27, 0x59, 0xd4, 0xf4, 0xd6, 0x84, 0xb2, 0xc5, 0x05, 0x6d, 0x5b, 0x17, 0x7a, 0xf0, 0xfa, 0x8a, 0xa9, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 15643327852135767324, note_rho: [ 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, @@ -118,821 +135,956 @@ pub(crate) fn test_vectors() -> Vec { }, TestVector { sk: [ - 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, - 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, - 0x99, 0x0e, 0xd8, 0x3d, + 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, + 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, + 0x1d, 0xdf, 0x65, 0x8d, ], ask: [ - 0x41, 0xd4, 0x7c, 0xc9, 0x63, 0x13, 0xb4, 0x82, 0x1d, 0xfc, 0x12, 0x96, 0x51, 0xc3, - 0x13, 0x7f, 0x44, 0xd9, 0xca, 0xd1, 0x6b, 0x3d, 0xc0, 0x81, 0x33, 0xc3, 0xd2, 0xdf, - 0x0d, 0x0c, 0x53, 0x20, + 0x09, 0x25, 0x99, 0x63, 0x5a, 0xdb, 0x8e, 0x4e, 0x49, 0x04, 0x8d, 0x69, 0xd7, 0xfd, + 0x8c, 0xbd, 0x6a, 0x19, 0xda, 0x87, 0x4e, 0x63, 0xdd, 0xdc, 0xd9, 0xee, 0x13, 0xbf, + 0xa5, 0xce, 0x3b, 0x16, ], ak: [ - 0x6d, 0xe1, 0x34, 0x98, 0x30, 0xd6, 0x6d, 0x7b, 0x97, 0xfe, 0x23, 0x1f, 0xc7, 0xb0, - 0x2a, 0xd6, 0x43, 0x23, 0x62, 0x9c, 0xfe, 0xd1, 0xe3, 0xaa, 0x24, 0xef, 0x05, 0x2f, - 0x56, 0xe4, 0x00, 0x2a, + 0x6e, 0x44, 0x56, 0x73, 0x37, 0xc9, 0xa0, 0x26, 0xff, 0x00, 0xae, 0x91, 0x8b, 0xe7, + 0xc0, 0x8e, 0x50, 0x20, 0x44, 0x98, 0xbb, 0x43, 0x12, 0x30, 0x28, 0x4d, 0x05, 0xf1, + 0xce, 0x53, 0xef, 0x3f, + ], + isk: [ + 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, + 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, + 0x89, 0x26, 0xc1, 0x03, + ], + ik: [ + 0x39, 0x62, 0x5b, 0x51, 0xaa, 0x0a, 0x3d, 0xde, 0x54, 0x6e, 0xde, 0x39, 0xa1, 0x23, + 0x2f, 0xa9, 0xba, 0xe8, 0x71, 0xab, 0x4f, 0x18, 0xe9, 0x0e, 0x5a, 0xe8, 0x03, 0x8c, + 0xce, 0xef, 0x66, 0x37, ], nk: [ - 0xa8, 0xb7, 0x3d, 0x97, 0x9b, 0x6e, 0xaa, 0xda, 0x89, 0x24, 0xbc, 0xbd, 0xc6, 0x3a, - 0x9e, 0xf4, 0xe8, 0x73, 0x46, 0xf2, 0x30, 0xab, 0xa6, 0xbb, 0xe1, 0xe2, 0xb4, 0x3c, - 0x5b, 0xea, 0x6b, 0x22, + 0x26, 0x84, 0x71, 0xe4, 0x66, 0xfe, 0x31, 0x2d, 0xd2, 0x07, 0x5d, 0x1a, 0x1a, 0x07, + 0xd8, 0x9b, 0x3e, 0xd2, 0x69, 0xba, 0x73, 0x97, 0xcf, 0x80, 0x14, 0xdd, 0x93, 0xbf, + 0xad, 0xd9, 0xa7, 0x34, ], rivk: [ - 0xda, 0xcb, 0x2f, 0x2a, 0x9c, 0xed, 0x36, 0x31, 0x71, 0x82, 0x1a, 0xaf, 0x5d, 0x8c, - 0xd9, 0x02, 0xbc, 0x5e, 0x3a, 0x5a, 0x41, 0xfb, 0x51, 0xae, 0x61, 0xa9, 0xf0, 0x2d, - 0xc8, 0x9d, 0x1d, 0x12, + 0x8d, 0x5e, 0x27, 0x86, 0xb5, 0x03, 0xc4, 0x65, 0xc7, 0x49, 0x03, 0x73, 0x46, 0x53, + 0xda, 0xff, 0xa3, 0x7a, 0x02, 0xad, 0x69, 0x76, 0x1a, 0x7c, 0x8a, 0x4d, 0x79, 0x83, + 0x02, 0xac, 0xe2, 0x3c, ], ivk: [ - 0x56, 0x3a, 0x6d, 0xb6, 0x0c, 0x74, 0xc2, 0xdb, 0x08, 0x49, 0x2c, 0xba, 0xe3, 0xbb, - 0x08, 0x3f, 0x1a, 0xea, 0xbf, 0xfb, 0xcf, 0x42, 0x55, 0x1d, 0x0a, 0xc6, 0x4f, 0x26, - 0x90, 0x53, 0x67, 0x11, + 0x35, 0xee, 0x37, 0x20, 0xc5, 0x5b, 0x02, 0x49, 0x75, 0x66, 0xa2, 0x50, 0x5d, 0x28, + 0x59, 0x60, 0xab, 0xf8, 0xc0, 0x5e, 0x68, 0x46, 0x9e, 0xad, 0x23, 0x91, 0xc9, 0x50, + 0xd6, 0xee, 0xc1, 0x10, ], ovk: [ - 0x71, 0xcd, 0x30, 0x64, 0x0f, 0xdb, 0x63, 0xf8, 0xd1, 0x30, 0x50, 0x29, 0xe9, 0x40, - 0xe5, 0x3f, 0xd5, 0xec, 0x04, 0xa8, 0xcc, 0xad, 0x41, 0x95, 0x78, 0xc2, 0x42, 0xfe, - 0xc0, 0x5b, 0x9a, 0xf7, + 0x60, 0x1a, 0xa8, 0xb5, 0x2f, 0xa8, 0x6b, 0x79, 0x5a, 0x18, 0x56, 0x0b, 0xcc, 0xc8, + 0x3d, 0xb1, 0xb5, 0xf9, 0x88, 0x25, 0x3c, 0xdd, 0x82, 0xf8, 0x84, 0x79, 0x2a, 0x04, + 0x25, 0x6f, 0x7b, 0x6d, ], dk: [ - 0x9d, 0x9b, 0xd4, 0x45, 0x25, 0xe7, 0xae, 0x06, 0xb0, 0x3a, 0xe6, 0xd4, 0xae, 0xcd, - 0xe6, 0xae, 0x09, 0x27, 0xa7, 0xc6, 0x67, 0xd5, 0xd9, 0xf8, 0x17, 0x6b, 0x54, 0x46, - 0x95, 0xdf, 0xec, 0x11, + 0x8a, 0x86, 0x44, 0xba, 0x40, 0xd0, 0xd0, 0x17, 0xf8, 0x1b, 0x04, 0xbb, 0x40, 0x0c, + 0x1b, 0xf8, 0x41, 0xfa, 0xce, 0x94, 0x6d, 0xc9, 0x8e, 0xc5, 0xde, 0xc6, 0xdd, 0x8f, + 0x9c, 0x32, 0x58, 0xee, ], default_d: [ - 0x78, 0x07, 0xca, 0x65, 0x08, 0x58, 0x81, 0x4d, 0x50, 0x22, 0xa8, + 0x44, 0x44, 0x93, 0xdb, 0xbc, 0x1a, 0x29, 0xe5, 0xe2, 0x6f, 0x6c, ], default_pk_d: [ - 0x3d, 0x3d, 0xe4, 0xd5, 0x2c, 0x77, 0xfd, 0x0b, 0x63, 0x0a, 0x40, 0xdc, 0x38, 0x21, - 0x24, 0x87, 0xb2, 0xff, 0x6e, 0xee, 0xf5, 0x6d, 0x8c, 0x6a, 0x61, 0x63, 0xe8, 0x54, - 0xaf, 0xf0, 0x41, 0x89, + 0x92, 0xcc, 0x30, 0xfa, 0xcd, 0x3a, 0xd8, 0xe6, 0xe4, 0xbb, 0xe6, 0xde, 0xdc, 0x71, + 0x9a, 0x09, 0x42, 0xaa, 0xf2, 0x77, 0xd6, 0xab, 0x39, 0x29, 0x2c, 0x26, 0x75, 0x78, + 0x15, 0x14, 0xd8, 0x93, ], internal_rivk: [ - 0x8a, 0x22, 0xa7, 0xf5, 0xa1, 0xe9, 0x1a, 0x92, 0xad, 0x39, 0x4b, 0x18, 0xeb, 0x73, - 0x38, 0xb5, 0x92, 0x47, 0x0d, 0xd4, 0x2b, 0xe8, 0xef, 0x84, 0xc9, 0x3e, 0x7c, 0xd8, - 0x45, 0xec, 0xfa, 0x32, + 0xc8, 0x17, 0xbf, 0x0f, 0x2d, 0xe1, 0xd1, 0xa4, 0x12, 0x52, 0x73, 0xb1, 0x15, 0x71, + 0xca, 0xe0, 0x67, 0x0c, 0xe3, 0xe4, 0x45, 0x6f, 0xbe, 0x0e, 0xb9, 0x03, 0x57, 0xda, + 0x15, 0xea, 0x2b, 0x03, ], internal_ivk: [ - 0x12, 0x11, 0x83, 0xcb, 0x3b, 0x8d, 0x06, 0xf5, 0x99, 0xbb, 0x38, 0xb3, 0x73, 0x22, - 0x85, 0x1e, 0x5f, 0xc9, 0x5a, 0xd0, 0xc9, 0x70, 0x7e, 0xe8, 0x5f, 0xb6, 0x5e, 0x21, - 0xf1, 0xa3, 0x0d, 0x13, + 0xcb, 0x28, 0xb7, 0xb9, 0x46, 0xe8, 0xf0, 0xb1, 0xa5, 0xda, 0x87, 0x6d, 0xda, 0x0c, + 0xac, 0x64, 0x1f, 0xc7, 0xfc, 0x16, 0x4e, 0x18, 0x99, 0xa6, 0xa5, 0xe0, 0xd8, 0x24, + 0x8c, 0xb1, 0x72, 0x3c, ], internal_ovk: [ - 0x93, 0x25, 0x2b, 0x24, 0xb4, 0x91, 0xd9, 0xc9, 0xc9, 0x97, 0x65, 0xc8, 0x4d, 0x4a, - 0xc7, 0xc2, 0xbf, 0xf0, 0x54, 0xcd, 0x9c, 0xad, 0xcd, 0x3e, 0x01, 0xb2, 0x6f, 0x21, - 0xe2, 0x84, 0x09, 0x09, + 0x6c, 0x94, 0xe6, 0xe4, 0x55, 0x9e, 0x70, 0xca, 0x50, 0xc5, 0x81, 0x25, 0x94, 0xf7, + 0x5c, 0x22, 0x93, 0x5d, 0x91, 0xea, 0xf7, 0x23, 0x56, 0x8e, 0xae, 0x2f, 0x9d, 0xc4, + 0xe9, 0x66, 0x0b, 0x53, ], internal_dk: [ - 0x6e, 0xea, 0x18, 0xfd, 0x0d, 0x50, 0x70, 0x7f, 0x90, 0xdf, 0x00, 0x2c, 0xbf, 0x30, - 0x9e, 0xca, 0x3c, 0x00, 0xd3, 0x98, 0xae, 0xde, 0x1f, 0xdc, 0x2a, 0xbf, 0xfc, 0x88, - 0x35, 0x38, 0x59, 0xaf, + 0x74, 0xb6, 0xa8, 0xee, 0x5b, 0x9b, 0x14, 0x84, 0x5e, 0x3e, 0x80, 0x7b, 0x84, 0x66, + 0x8e, 0xe4, 0xe4, 0x57, 0xd6, 0x40, 0xe3, 0xa3, 0xff, 0x61, 0x43, 0x6f, 0xe3, 0xda, + 0xcb, 0xaa, 0x01, 0xe9, ], - note_v: 4481649511318637270, + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + note_v: 654021594278506020, note_rho: [ - 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, - 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, - 0x2c, 0x8d, 0x13, 0x09, + 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, + 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, + 0x79, 0x0f, 0xe5, 0x3e, ], note_rseed: [ - 0x13, 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, - 0xe1, 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, - 0x33, 0xa9, 0x7f, 0xa6, + 0x29, 0xfe, 0xf2, 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, + 0xa0, 0x08, 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, + 0xaa, 0xbe, 0x3f, 0x1a, ], note_cmx: [ - 0xc7, 0xad, 0x79, 0x4c, 0x56, 0x3e, 0x32, 0xca, 0xd4, 0x7d, 0x47, 0xdc, 0xda, 0x78, - 0x84, 0x69, 0x28, 0x48, 0xdc, 0xe2, 0x9b, 0xa4, 0xfe, 0xbd, 0x93, 0x20, 0x2b, 0x73, - 0x05, 0xf9, 0x03, 0x00, + 0x23, 0x60, 0xbf, 0xad, 0x63, 0xb5, 0x1e, 0xfb, 0x16, 0x00, 0xa7, 0x6f, 0xf7, 0x3a, + 0xd7, 0x33, 0x54, 0x11, 0x31, 0x8a, 0x6a, 0x4b, 0x02, 0xb7, 0x57, 0x78, 0x3f, 0x01, + 0xdb, 0xa0, 0x40, 0x14, ], note_nf: [ - 0x2c, 0xf0, 0x67, 0xbc, 0x21, 0xd6, 0x63, 0x20, 0xe5, 0x1b, 0x9f, 0xbd, 0xc8, 0xae, - 0x03, 0x1c, 0x2c, 0x96, 0x37, 0x3d, 0xb4, 0x3b, 0x7b, 0x1a, 0x45, 0x05, 0x6c, 0x00, - 0xc6, 0x5d, 0x43, 0x20, + 0xd7, 0xa8, 0x9c, 0xee, 0x48, 0x18, 0xfc, 0x86, 0x4b, 0x11, 0xa0, 0x8f, 0x65, 0xad, + 0x3d, 0xbf, 0x26, 0xd4, 0x37, 0x99, 0x7f, 0x6a, 0xb8, 0xa6, 0x02, 0x58, 0x3b, 0xfc, + 0x6a, 0x62, 0x04, 0x10, ], }, TestVector { sk: [ - 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, 0xda, 0xe6, 0x9c, - 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, 0x93, 0x1d, 0xe5, - 0x18, 0x85, 0x68, 0x78, + 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, + 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, + 0x1c, 0xd0, 0x74, 0xa5, ], ask: [ - 0xce, 0x8b, 0x65, 0xa7, 0x23, 0x65, 0x11, 0xb2, 0xea, 0xf1, 0x9f, 0x72, 0xa3, 0xd6, - 0xdb, 0x7d, 0x06, 0x2b, 0x66, 0xf5, 0x16, 0x30, 0x7d, 0x19, 0x87, 0x06, 0xe5, 0xf6, - 0x92, 0x8e, 0x16, 0x15, + 0xfa, 0x33, 0x7b, 0xa3, 0x9b, 0x90, 0x62, 0xd5, 0x11, 0x74, 0x68, 0x63, 0x83, 0xc8, + 0xa5, 0x99, 0x5a, 0x47, 0x6e, 0xc1, 0xe0, 0xc7, 0x0b, 0x68, 0xa2, 0x00, 0x3c, 0xd4, + 0x79, 0x25, 0x3e, 0x26, ], ak: [ - 0xef, 0xa5, 0xf1, 0xde, 0xbe, 0xea, 0xd0, 0x94, 0x0a, 0x61, 0x9c, 0xe0, 0x01, 0x7b, - 0xed, 0xb4, 0x26, 0x65, 0x7b, 0x2d, 0x07, 0x40, 0x66, 0x64, 0xd8, 0x95, 0x31, 0x2e, - 0xa1, 0xc3, 0xb3, 0x34, + 0xc4, 0xfd, 0xec, 0x5a, 0xc0, 0xc4, 0x8b, 0xe1, 0xf2, 0xb0, 0x60, 0xfa, 0x21, 0x40, + 0x7f, 0x85, 0xd2, 0xd4, 0x52, 0xf2, 0x8f, 0xc6, 0x42, 0xed, 0x67, 0x50, 0xec, 0x6d, + 0x8c, 0xf8, 0x7c, 0x22, + ], + isk: [ + 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, 0x83, 0x88, + 0xe7, 0x6c, 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, + 0xa9, 0x59, 0xcc, 0x97, + ], + ik: [ + 0x78, 0xd1, 0xdc, 0xef, 0xee, 0x06, 0xc5, 0x66, 0x7f, 0x19, 0x76, 0xa5, 0x66, 0x73, + 0x13, 0x0b, 0x9e, 0x72, 0x05, 0xf3, 0xa5, 0x0a, 0xd1, 0x96, 0x00, 0x89, 0x6c, 0xe5, + 0xc2, 0x64, 0xfa, 0xf6, ], nk: [ - 0x04, 0x51, 0x4e, 0xa0, 0x48, 0xb9, 0x43, 0x63, 0xde, 0xa7, 0xcb, 0x3b, 0xe8, 0xd6, - 0x25, 0x82, 0xac, 0x52, 0x92, 0x2e, 0x08, 0x65, 0xf6, 0x62, 0x74, 0x3b, 0x05, 0xea, - 0xe8, 0x71, 0x5f, 0x17, + 0x9d, 0xca, 0xb0, 0x5e, 0x6c, 0x24, 0x15, 0xad, 0x65, 0xb6, 0x4e, 0x6a, 0x9a, 0xec, + 0xb1, 0x53, 0x60, 0x77, 0x87, 0x8d, 0x85, 0xc5, 0x33, 0x9a, 0x2b, 0x59, 0x79, 0x06, + 0xdf, 0xba, 0x9f, 0x3e, ], rivk: [ - 0x2a, 0x32, 0x8f, 0x99, 0x4f, 0x6e, 0x5a, 0xd2, 0x9c, 0xa8, 0x11, 0xed, 0x34, 0x49, - 0x68, 0xea, 0x2c, 0xfc, 0x3f, 0xd2, 0x31, 0x03, 0x0e, 0x37, 0xbb, 0xd5, 0x6d, 0xb4, - 0x26, 0x40, 0x23, 0x1c, + 0x4b, 0x61, 0x99, 0xae, 0x4c, 0x65, 0x21, 0x61, 0x11, 0x3d, 0x78, 0x75, 0xfa, 0x2f, + 0x85, 0xde, 0x60, 0xa1, 0xa2, 0x01, 0x73, 0x75, 0x9e, 0xa6, 0xb7, 0xcd, 0x8e, 0xc7, + 0xe5, 0x9b, 0x20, 0x35, ], ivk: [ - 0x60, 0x9e, 0xcb, 0xc3, 0xd8, 0xce, 0xe3, 0xbe, 0x2b, 0x2a, 0x23, 0x62, 0x95, 0x1f, - 0x58, 0xb7, 0x44, 0x82, 0xad, 0xfa, 0xee, 0xe1, 0xc4, 0x0f, 0x94, 0x03, 0x04, 0x40, - 0xf5, 0x58, 0xaa, 0x30, + 0x1d, 0x9e, 0x91, 0xca, 0x38, 0x82, 0x79, 0x59, 0x18, 0x53, 0x6b, 0x51, 0x14, 0xae, + 0x21, 0x63, 0x57, 0x62, 0xf1, 0x49, 0xc9, 0x59, 0x09, 0x80, 0x3f, 0x36, 0xea, 0x9f, + 0xca, 0x71, 0x1f, 0x2f, ], ovk: [ - 0xdf, 0xd3, 0x0f, 0x62, 0xaa, 0x31, 0x9c, 0x6f, 0x53, 0xe2, 0x4c, 0x1f, 0x48, 0xc1, - 0xde, 0x96, 0x1b, 0x90, 0x01, 0xcb, 0x98, 0x8b, 0x80, 0xb3, 0xed, 0xa2, 0x44, 0xfc, - 0xfe, 0xb2, 0x5f, 0x83, + 0x94, 0x30, 0xaf, 0xfd, 0x7e, 0x29, 0x2b, 0xa8, 0xf7, 0xab, 0x0c, 0xc1, 0xfa, 0xcd, + 0x67, 0xb4, 0x99, 0x59, 0x4b, 0xf6, 0x8d, 0x93, 0xeb, 0x3a, 0xb7, 0x51, 0x5d, 0x88, + 0xa0, 0x87, 0xe0, 0xef, ], dk: [ - 0x23, 0x6b, 0xc3, 0xf3, 0xd0, 0x2f, 0x96, 0x02, 0x80, 0xee, 0xde, 0xde, 0x10, 0x8d, - 0x36, 0x85, 0x04, 0x9f, 0x23, 0x9a, 0xa6, 0x7c, 0x48, 0x55, 0x8f, 0x7c, 0x01, 0xd3, - 0xfd, 0x46, 0x9e, 0xcd, + 0x5f, 0x15, 0x10, 0x14, 0xd0, 0x9f, 0xe9, 0x14, 0x68, 0x52, 0x66, 0x1e, 0xcb, 0xe3, + 0x3c, 0x1e, 0xea, 0xcc, 0x6d, 0xd9, 0xf7, 0x3b, 0xd0, 0xd4, 0xdc, 0x82, 0x5f, 0x4f, + 0x2f, 0xc2, 0x94, 0xde, ], default_d: [ - 0x64, 0x24, 0xf7, 0x1a, 0x3a, 0xd1, 0x97, 0x42, 0x64, 0x98, 0xf4, + 0x10, 0x23, 0x07, 0x3f, 0x95, 0x67, 0xce, 0xa8, 0x22, 0x82, 0xe1, ], default_pk_d: [ - 0xec, 0xcb, 0x6a, 0x57, 0x80, 0x20, 0x42, 0x37, 0x98, 0x72, 0x32, 0xbc, 0x09, 0x8f, - 0x89, 0xac, 0xc4, 0x75, 0xc3, 0xf7, 0x4b, 0xd6, 0x9e, 0x2f, 0x35, 0xd4, 0x47, 0x36, - 0xf4, 0x8f, 0x3c, 0x14, + 0x28, 0xb9, 0x35, 0x6e, 0x43, 0xb5, 0x75, 0x78, 0x1a, 0x09, 0x02, 0xbd, 0xbc, 0x93, + 0xe5, 0x57, 0x98, 0x78, 0xa8, 0x41, 0x63, 0x14, 0x70, 0xb4, 0x07, 0x9b, 0x05, 0x90, + 0x18, 0xa5, 0x20, 0x0d, ], internal_rivk: [ - 0x0a, 0xa9, 0xaa, 0xaa, 0x2c, 0xf1, 0x84, 0x90, 0xdd, 0xf9, 0xa7, 0xe5, 0x21, 0x07, - 0x14, 0x07, 0xea, 0x9b, 0xff, 0xfe, 0x84, 0x34, 0x29, 0xbc, 0x94, 0xa2, 0x88, 0xe8, - 0xa6, 0x06, 0xa7, 0x10, + 0xb2, 0x63, 0x58, 0x05, 0xef, 0x00, 0x78, 0xaf, 0x79, 0x32, 0xe3, 0x93, 0x40, 0x82, + 0x94, 0xcb, 0xc0, 0xf3, 0xfa, 0x93, 0x56, 0x8f, 0x2b, 0xbe, 0x07, 0x29, 0x8f, 0xc2, + 0xba, 0xf9, 0x53, 0x3a, ], internal_ivk: [ - 0xa0, 0x6a, 0xbd, 0x29, 0xd5, 0xa1, 0x99, 0xe1, 0xc2, 0x10, 0x25, 0xb0, 0x33, 0x7e, - 0x94, 0x1f, 0x6d, 0x4d, 0x84, 0xeb, 0x7c, 0xc3, 0x5a, 0x39, 0x7f, 0x9e, 0x75, 0x3f, - 0xda, 0xed, 0x81, 0x0d, + 0xcb, 0x69, 0xdc, 0x54, 0x1d, 0x52, 0x7e, 0x1c, 0x1f, 0x4c, 0x7a, 0xd7, 0xd2, 0x67, + 0xe3, 0x18, 0xed, 0xaa, 0x79, 0x15, 0x61, 0xcd, 0x5c, 0xee, 0x51, 0x8e, 0x14, 0xaa, + 0xaa, 0x4c, 0x0e, 0x08, ], internal_ovk: [ - 0xf8, 0x2e, 0xb2, 0x49, 0x06, 0xe2, 0x94, 0xff, 0x65, 0x71, 0xac, 0x7d, 0x83, 0x68, - 0xea, 0x82, 0x80, 0xd4, 0x22, 0xf3, 0x47, 0x7c, 0xe7, 0x2a, 0xef, 0x5f, 0x9b, 0x9e, - 0xca, 0x48, 0x46, 0x8f, + 0x25, 0x58, 0x8e, 0xdb, 0xf6, 0x77, 0x42, 0xab, 0x55, 0xca, 0x95, 0xa9, 0x0a, 0xe0, + 0xe0, 0x29, 0xa8, 0x7f, 0xc4, 0xcf, 0x9c, 0xf3, 0xf7, 0x00, 0x65, 0xe0, 0x64, 0xec, + 0xc4, 0xd6, 0x45, 0x8e, ], internal_dk: [ - 0x36, 0x56, 0xb5, 0x45, 0xa5, 0x0a, 0x6b, 0x26, 0x28, 0x74, 0x76, 0x64, 0x1b, 0x2b, - 0x68, 0xc6, 0x3c, 0x36, 0xf3, 0x32, 0xe7, 0x45, 0x57, 0xe9, 0x16, 0x05, 0x0f, 0x0b, - 0x91, 0x11, 0x17, 0x9b, + 0xad, 0x38, 0x62, 0x22, 0xdd, 0xd6, 0x65, 0x3b, 0xed, 0x73, 0x36, 0x64, 0x3d, 0xcb, + 0x63, 0x51, 0x4a, 0x25, 0x17, 0x7a, 0x81, 0xf5, 0x8f, 0x84, 0x06, 0x84, 0x4e, 0x16, + 0x42, 0xdb, 0x6e, 0x03, ], - note_v: 14496603531126387959, + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + note_v: 15839468553911279642, note_rho: [ - 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, - 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, 0x1a, 0x84, 0xb2, 0x7d, 0xb5, - 0x9a, 0x4a, 0x15, 0x3d, + 0xce, 0xcb, 0x8c, 0xb8, 0xa5, 0xda, 0x01, 0x30, 0x71, 0x52, 0xf1, 0x39, 0x36, 0xa2, + 0x70, 0x57, 0x26, 0x70, 0xdc, 0x82, 0xd3, 0x90, 0x26, 0xc6, 0xcb, 0x4c, 0xd4, 0xb0, + 0xf7, 0xf5, 0xaa, 0x2a, ], note_rseed: [ - 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, - 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, - 0xcf, 0x4a, 0x0d, 0x9c, + 0x4f, 0x5a, 0x53, 0x41, 0xec, 0x5d, 0xd7, 0x15, 0x40, 0x6f, 0x2f, 0xdd, 0x2a, 0xfa, + 0x73, 0x3f, 0x5f, 0x64, 0x1c, 0x8c, 0x21, 0x86, 0x2a, 0x1b, 0xaf, 0xce, 0x26, 0x09, + 0xd9, 0xee, 0xcf, 0xa1, ], note_cmx: [ - 0x03, 0xce, 0x20, 0xce, 0xa1, 0x94, 0xb7, 0x55, 0x9a, 0x8a, 0x90, 0x47, 0x1d, 0x28, - 0xa3, 0xc0, 0x53, 0xc3, 0x72, 0x0a, 0xd4, 0x9f, 0x40, 0xd2, 0x7c, 0x2d, 0xcc, 0xe3, - 0x35, 0x00, 0x56, 0x16, + 0x44, 0x41, 0x60, 0xcb, 0x6e, 0x4c, 0xe5, 0x98, 0xe9, 0x48, 0x82, 0x6a, 0x81, 0x6f, + 0xfa, 0xdb, 0xfb, 0xd2, 0x4b, 0xe0, 0x1d, 0x4e, 0xfd, 0x41, 0x37, 0x8f, 0x79, 0x2e, + 0xdb, 0xa9, 0xf0, 0x14, ], note_nf: [ - 0x16, 0xfa, 0x2c, 0x34, 0x97, 0xfc, 0x09, 0xad, 0x90, 0xdd, 0x34, 0x92, 0x02, 0xa2, - 0x4b, 0x69, 0x89, 0x2d, 0xc8, 0x06, 0x29, 0xb2, 0xd1, 0xbf, 0xeb, 0xaf, 0x41, 0x70, - 0x8f, 0x0f, 0xb1, 0x0c, + 0xec, 0xe2, 0x42, 0x8b, 0x0b, 0x0a, 0x02, 0x26, 0xbb, 0x88, 0xf6, 0x4f, 0xfe, 0x2e, + 0x9c, 0x5e, 0x6d, 0x4c, 0x44, 0x3d, 0xa9, 0x46, 0xb0, 0x0d, 0x0d, 0x8f, 0x80, 0x1c, + 0x2f, 0x2d, 0xa9, 0x03, ], }, TestVector { sk: [ - 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, - 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, - 0xba, 0x18, 0xd1, 0xdb, + 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, 0x9c, 0xfb, + 0xdf, 0x73, 0xca, 0xec, 0x65, 0x60, 0x40, 0x37, 0x31, 0x4f, 0xaa, 0xce, 0xb5, 0x62, + 0x18, 0xc6, 0xbd, 0x30, ], ask: [ - 0x42, 0x6a, 0x78, 0x44, 0xf3, 0x05, 0xb9, 0xd4, 0xe0, 0x7e, 0xa5, 0x2a, 0x39, 0x00, - 0x1c, 0x9b, 0x33, 0x6c, 0xfc, 0x0d, 0x6f, 0xa1, 0x5e, 0xf3, 0xd1, 0x1c, 0x3d, 0x7b, - 0x74, 0xf0, 0x8c, 0x2d, + 0x2c, 0x04, 0x9c, 0x69, 0xcf, 0x07, 0x87, 0x81, 0x61, 0xc0, 0xa3, 0x55, 0x24, 0x07, + 0x8a, 0x46, 0x55, 0x30, 0xb6, 0xec, 0xab, 0x1b, 0xd8, 0xd7, 0x48, 0xb1, 0xd8, 0x16, + 0x9e, 0x91, 0xe6, 0x08, ], ak: [ - 0xb1, 0xe0, 0xac, 0xbc, 0x69, 0xbf, 0x37, 0x7b, 0x85, 0xab, 0xf0, 0xf5, 0xa1, 0x0b, - 0xe7, 0x2c, 0x3b, 0x64, 0x00, 0x06, 0xff, 0x08, 0x50, 0x52, 0x80, 0xe4, 0xf0, 0x0f, - 0xad, 0xf7, 0x63, 0x28, + 0x7d, 0xcf, 0x33, 0x91, 0x77, 0x05, 0x64, 0xc8, 0xf9, 0xe7, 0xc1, 0x7b, 0xf6, 0x7f, + 0x05, 0x4e, 0x5b, 0xd0, 0x40, 0xc4, 0xde, 0x28, 0xd8, 0xdd, 0x46, 0xd5, 0x8d, 0xf8, + 0xc5, 0xee, 0xe6, 0x2d, + ], + isk: [ + 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, 0xcd, 0x08, + 0xcb, 0x05, 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, + 0x71, 0x62, 0x69, 0xb9, + ], + ik: [ + 0x39, 0xc4, 0x51, 0xf4, 0xd8, 0xdd, 0xcf, 0x69, 0x05, 0xed, 0xd8, 0x82, 0x5a, 0xd9, + 0x81, 0xb9, 0xe7, 0x3c, 0xa6, 0x83, 0x1c, 0xa2, 0xb3, 0xd7, 0xe8, 0xce, 0xf3, 0xd0, + 0xba, 0xaa, 0x31, 0x1b, ], nk: [ - 0xcf, 0x36, 0xad, 0x6a, 0x06, 0x6c, 0xd2, 0x13, 0xe1, 0xd7, 0x67, 0xab, 0x07, 0x1d, - 0xc1, 0x16, 0x78, 0x85, 0xc4, 0x16, 0x8b, 0xc2, 0xe2, 0x17, 0x54, 0x48, 0x56, 0x3a, - 0xd1, 0x3f, 0x33, 0x3d, + 0x8d, 0xa4, 0xba, 0x62, 0x70, 0xae, 0x6d, 0x89, 0xa8, 0x6a, 0x06, 0xbc, 0x84, 0xbb, + 0x41, 0x53, 0xac, 0xbc, 0x5f, 0x7d, 0xb7, 0xa9, 0x55, 0x6c, 0x57, 0x79, 0xcf, 0x76, + 0xb7, 0x66, 0x25, 0x03, ], rivk: [ - 0xc4, 0x1b, 0xba, 0xd3, 0x51, 0x05, 0xa8, 0x03, 0x14, 0xb7, 0x96, 0x24, 0xb6, 0x75, - 0x24, 0x12, 0x20, 0xb3, 0x31, 0xf1, 0x25, 0x92, 0x61, 0x7b, 0xdb, 0x70, 0x5b, 0xfc, - 0xce, 0x72, 0xae, 0x38, + 0xf3, 0x50, 0x76, 0x23, 0x5d, 0x13, 0xd3, 0x20, 0xdd, 0xd5, 0x1c, 0xf8, 0x7f, 0xaa, + 0x09, 0x40, 0xed, 0x38, 0xa6, 0x06, 0xae, 0xe1, 0x8b, 0x90, 0x18, 0x30, 0xa8, 0x87, + 0x87, 0xb2, 0xa1, 0x32, ], ivk: [ - 0xf7, 0x9f, 0xe8, 0x02, 0xe4, 0xd2, 0x43, 0x07, 0xa6, 0xaa, 0xf8, 0x5d, 0x19, 0xf5, - 0xe0, 0x83, 0x37, 0x40, 0xba, 0xe5, 0x98, 0xdc, 0x7c, 0x88, 0x0a, 0xc6, 0x09, 0x63, - 0x1d, 0xe1, 0x58, 0x19, + 0xcc, 0x27, 0xbc, 0x8f, 0xda, 0x30, 0x60, 0xa5, 0x95, 0x26, 0x23, 0xef, 0x80, 0xaa, + 0x64, 0x1c, 0x58, 0x43, 0x2a, 0x82, 0xd3, 0x26, 0x8b, 0x35, 0x89, 0xb1, 0x45, 0xf1, + 0x52, 0x0b, 0x43, 0x1d, ], ovk: [ - 0xf9, 0x63, 0x66, 0xbc, 0x6e, 0xab, 0xd2, 0x32, 0x54, 0x9e, 0xbb, 0x43, 0xb4, 0xed, - 0x6f, 0xd8, 0x1d, 0x33, 0x03, 0x73, 0xc5, 0xb5, 0x66, 0x90, 0x4e, 0x9a, 0xf1, 0x1a, - 0x6b, 0xab, 0x8d, 0x77, + 0xae, 0xee, 0xcc, 0x69, 0x80, 0xf9, 0x7c, 0x1e, 0x6f, 0x89, 0x09, 0xaf, 0x63, 0x48, + 0xe4, 0xbd, 0x20, 0x83, 0x65, 0x81, 0x0d, 0x1b, 0x99, 0xe8, 0x47, 0x56, 0xa3, 0xcb, + 0xdf, 0x4c, 0x35, 0x98, ], dk: [ - 0x80, 0x3e, 0x34, 0x85, 0x73, 0x02, 0x2b, 0xf8, 0x93, 0x2f, 0x23, 0xee, 0x7a, 0x32, - 0x5e, 0xa2, 0x83, 0x87, 0x9c, 0x65, 0x24, 0x12, 0xb8, 0x60, 0x6b, 0xe3, 0x19, 0x8c, - 0x4b, 0x78, 0x2c, 0x47, + 0x63, 0xc4, 0xf6, 0xcd, 0x2c, 0xbd, 0xbb, 0x5a, 0x04, 0x81, 0xba, 0x93, 0x4f, 0xd1, + 0xc1, 0xd7, 0x4c, 0x1c, 0xeb, 0xf0, 0xcb, 0x58, 0x39, 0x78, 0xc8, 0x5b, 0xa2, 0x0b, + 0x14, 0x81, 0x89, 0x17, ], default_d: [ - 0xdb, 0x8c, 0x30, 0x55, 0x24, 0xbc, 0x0d, 0xea, 0xa8, 0x5d, 0x97, + 0xa1, 0xc6, 0x51, 0x16, 0xe0, 0x0a, 0x9b, 0x10, 0x51, 0x18, 0x0e, ], default_pk_d: [ - 0x04, 0xea, 0x8c, 0x13, 0x20, 0xff, 0xbb, 0xad, 0xfe, 0x96, 0xf0, 0xc6, 0xff, 0x16, - 0xb6, 0x07, 0x11, 0x1b, 0x55, 0x83, 0xbf, 0xb6, 0xf1, 0xea, 0x45, 0x27, 0x5e, 0xf2, - 0xaa, 0x2d, 0x87, 0x9b, + 0x1a, 0xea, 0xce, 0xdd, 0x51, 0x8a, 0x38, 0x57, 0x7d, 0x6a, 0x70, 0x90, 0x45, 0x59, + 0x72, 0x15, 0x5b, 0x34, 0x44, 0xb3, 0x24, 0x29, 0x34, 0x5d, 0x39, 0x67, 0x50, 0x87, + 0xbd, 0xcc, 0x39, 0xb1, ], internal_rivk: [ - 0x9e, 0x45, 0x2a, 0xb7, 0x2c, 0x6c, 0x8e, 0xcc, 0xf2, 0xe4, 0x39, 0xa0, 0xce, 0xc0, - 0xa0, 0xac, 0x39, 0x4a, 0x1a, 0xa1, 0x21, 0xac, 0x60, 0x32, 0xa7, 0xeb, 0xc2, 0x9d, - 0xb4, 0x85, 0x62, 0x26, + 0x69, 0xbe, 0x50, 0x0f, 0xdd, 0xc9, 0x8f, 0x2d, 0x11, 0x0f, 0x4e, 0xc6, 0x96, 0xd1, + 0xf5, 0x7c, 0xe6, 0x3d, 0x2c, 0xae, 0xd8, 0x85, 0x39, 0x74, 0x75, 0xc2, 0x5d, 0x21, + 0x09, 0x09, 0xf6, 0x1f, ], internal_ivk: [ - 0x3b, 0xa9, 0x3b, 0x0f, 0xc3, 0xf2, 0x7a, 0xb2, 0x17, 0x63, 0x5d, 0x03, 0xf9, 0x0d, - 0x0b, 0x84, 0x2d, 0x99, 0xa1, 0x2c, 0xdc, 0x37, 0xa8, 0x1c, 0x18, 0x1e, 0xc0, 0x18, - 0xe5, 0xf4, 0x4c, 0x11, + 0x32, 0xee, 0xca, 0x1a, 0xa6, 0x74, 0x76, 0x74, 0xb9, 0x75, 0x25, 0x5d, 0x08, 0x4b, + 0x03, 0x5b, 0x98, 0x51, 0xcd, 0x50, 0x18, 0xdd, 0xf6, 0x47, 0xce, 0xb9, 0xe1, 0xde, + 0x9e, 0x43, 0x9b, 0x2c, ], internal_ovk: [ - 0xe3, 0xc7, 0xf8, 0x6c, 0x1b, 0x23, 0x83, 0xb3, 0xbd, 0x41, 0xad, 0x1a, 0x8f, 0x11, - 0xef, 0xa2, 0x55, 0x4a, 0x41, 0x0a, 0x98, 0xc8, 0x92, 0x07, 0xae, 0xb4, 0x31, 0x9b, - 0x1a, 0xbd, 0x78, 0x79, + 0x43, 0x48, 0xf7, 0x3e, 0x04, 0x54, 0x47, 0x05, 0x59, 0xad, 0x5e, 0x42, 0x29, 0x37, + 0xb8, 0x78, 0x87, 0x4d, 0x64, 0x64, 0xf9, 0x94, 0x08, 0x04, 0x17, 0xeb, 0x16, 0xb6, + 0xd0, 0xac, 0x1b, 0xa4, ], internal_dk: [ - 0xd7, 0x1a, 0x68, 0xcf, 0xd6, 0xc7, 0x68, 0xf4, 0x30, 0x73, 0xf6, 0x98, 0x18, 0x9a, - 0xc7, 0x5e, 0xe4, 0x21, 0xb4, 0x20, 0x4b, 0xb6, 0xf3, 0xc5, 0xd0, 0xfc, 0x43, 0x28, - 0x49, 0xaa, 0x71, 0x61, + 0x27, 0x6d, 0x6e, 0xf9, 0xed, 0x58, 0xfa, 0x8a, 0x81, 0x18, 0x02, 0xbd, 0x3a, 0x0c, + 0x44, 0xd7, 0x9d, 0xbb, 0xe0, 0x6b, 0x94, 0x20, 0x0d, 0x43, 0x44, 0x28, 0x5b, 0x26, + 0x60, 0x03, 0xf4, 0x45, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 6792346249443327211, + note_v: 4573834453415770104, note_rho: [ - 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc, - 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, 0xe7, - 0x1a, 0x02, 0xaf, 0x11, + 0x21, 0xa9, 0xfb, 0x80, 0xad, 0x03, 0xbc, 0x0c, 0xda, 0x4a, 0x44, 0x94, 0x6c, 0x00, + 0xe1, 0xb1, 0xa1, 0xdf, 0x0e, 0x5b, 0x87, 0xb5, 0xbe, 0xce, 0x47, 0x7a, 0x70, 0x96, + 0x49, 0xe9, 0x50, 0x06, ], note_rseed: [ - 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, 0xb1, 0xfc, 0xe4, 0x67, 0x50, - 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, 0xc3, 0x82, 0x85, 0x7d, 0xee, - 0xcc, 0x40, 0xa9, 0x8d, + 0x05, 0x91, 0x39, 0x48, 0x12, 0x95, 0x1e, 0x1f, 0xe3, 0x89, 0x5b, 0x8c, 0xc3, 0xd1, + 0x4d, 0x2c, 0xf6, 0x55, 0x6d, 0xf6, 0xed, 0x4b, 0x4d, 0xdd, 0x3d, 0x9a, 0x69, 0xf5, + 0x33, 0x57, 0xd7, 0x76, ], note_cmx: [ - 0xa9, 0xb1, 0x1b, 0xaf, 0x30, 0x34, 0xb6, 0x5c, 0x64, 0x24, 0x84, 0x1b, 0xfe, 0x02, - 0x3f, 0x8e, 0xda, 0x13, 0x13, 0xc3, 0x0a, 0xa2, 0x7d, 0xe9, 0x2e, 0x21, 0xa1, 0x08, - 0x31, 0x6e, 0x82, 0x19, + 0x5f, 0x5f, 0x8c, 0xff, 0x89, 0xb1, 0xbe, 0xdc, 0x6f, 0x58, 0x4f, 0x0b, 0x85, 0x58, + 0x6a, 0x54, 0x4b, 0xc4, 0x25, 0x53, 0x88, 0xa5, 0xff, 0x72, 0xf6, 0x75, 0x13, 0x8b, + 0xcb, 0x70, 0xb2, 0x27, ], note_nf: [ - 0x72, 0xd6, 0x30, 0x89, 0x60, 0x35, 0x1f, 0x7b, 0x26, 0xfa, 0x64, 0x60, 0x3f, 0xe4, - 0xdf, 0xd8, 0x67, 0xbd, 0x5e, 0xb3, 0x67, 0xba, 0x2b, 0x7c, 0xa4, 0x91, 0xc9, 0x23, - 0xc0, 0xea, 0xd2, 0x22, + 0x8f, 0xca, 0x6e, 0x8b, 0x77, 0xab, 0x9d, 0x19, 0xf2, 0xf8, 0x35, 0x39, 0xa2, 0x91, + 0x29, 0x2f, 0xb1, 0x5e, 0x00, 0x50, 0xde, 0xd7, 0x77, 0x13, 0x3e, 0x75, 0x1e, 0x9f, + 0x0a, 0xe2, 0xff, 0x35, ], }, TestVector { sk: [ - 0x5f, 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0x2d, 0xd2, 0x1a, 0xfd, 0xbb, 0x5d, 0x47, - 0xfa, 0x9a, 0x6d, 0xd9, 0x84, 0xd5, 0x67, 0xdb, 0x28, 0x57, 0xb9, 0x27, 0xb7, 0xfa, - 0xe2, 0xdb, 0x58, 0x71, + 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, 0x9e, 0x68, + 0x62, 0x5a, 0x19, 0x24, 0x40, 0xea, 0x06, 0x82, 0x81, 0x23, 0xd9, 0x78, 0x84, 0x80, + 0x6f, 0x15, 0xfa, 0x08, ], ask: [ - 0x11, 0x80, 0x73, 0x28, 0x51, 0x64, 0xe6, 0x55, 0x73, 0x58, 0xfb, 0xc4, 0x1a, 0x81, - 0x35, 0xcb, 0x06, 0x2f, 0x86, 0x76, 0xcb, 0x61, 0xf9, 0xaa, 0x52, 0xd1, 0x9a, 0x09, - 0xfa, 0xc5, 0x58, 0x02, + 0xfa, 0x92, 0x86, 0xf7, 0x67, 0x77, 0x23, 0x5c, 0x74, 0x3d, 0xfa, 0xc1, 0xb8, 0x83, + 0x0d, 0x9f, 0xe3, 0x33, 0xca, 0xd7, 0x21, 0xd5, 0x49, 0xa9, 0x47, 0xc7, 0x5e, 0xce, + 0x7d, 0x00, 0xf5, 0x38, ], ak: [ - 0x0d, 0x26, 0x2d, 0xe3, 0x60, 0x94, 0x33, 0xfe, 0x5b, 0x7c, 0x86, 0x2b, 0xc4, 0x8e, - 0xf5, 0x6d, 0x83, 0x20, 0x09, 0xf7, 0x24, 0x2e, 0x1f, 0x7c, 0x77, 0x0a, 0x12, 0x24, - 0x1d, 0xfa, 0x28, 0x07, + 0x10, 0x07, 0x3a, 0x7a, 0xe1, 0x28, 0x59, 0x2d, 0xbe, 0xe5, 0x28, 0x2b, 0xc1, 0x24, + 0x1b, 0x94, 0x75, 0xa5, 0x98, 0x19, 0x62, 0xbd, 0xf2, 0x14, 0xe9, 0x35, 0xd9, 0xb3, + 0x27, 0xf0, 0x25, 0x24, + ], + isk: [ + 0xe2, 0xf5, 0x7e, 0x34, 0xfb, 0xc7, 0x54, 0x23, 0xc3, 0x73, 0x7f, 0x5b, 0x2a, 0x06, + 0x15, 0xf5, 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, + 0x2e, 0x19, 0xe5, 0x94, + ], + ik: [ + 0x2b, 0x5d, 0xe5, 0x60, 0x92, 0xfe, 0xa3, 0x1a, 0x8e, 0xa9, 0xf8, 0x70, 0x84, 0x7d, + 0xc1, 0xfa, 0x87, 0xfd, 0x3c, 0x25, 0xcf, 0x70, 0x9a, 0x0e, 0xff, 0xd6, 0x99, 0xc2, + 0x96, 0x41, 0x31, 0x6e, ], nk: [ - 0x51, 0xba, 0xf3, 0x33, 0xcf, 0xf1, 0xf2, 0xd0, 0xc7, 0xe3, 0xcf, 0xf4, 0xd3, 0x01, - 0x29, 0x9d, 0xc1, 0xef, 0xe9, 0x83, 0x00, 0x31, 0x4a, 0x54, 0x19, 0x38, 0x02, 0x9b, - 0x45, 0xcc, 0x15, 0x21, + 0x4f, 0xb7, 0x68, 0x10, 0x2e, 0x99, 0xbe, 0xfe, 0x6e, 0x76, 0xed, 0x4e, 0xea, 0x65, + 0x83, 0x54, 0x14, 0x78, 0x00, 0x4e, 0x96, 0x49, 0x26, 0xfd, 0x34, 0x70, 0x4a, 0xcc, + 0xd9, 0x2d, 0x0c, 0x1f, ], rivk: [ - 0x22, 0x8f, 0xeb, 0x79, 0x21, 0x98, 0x73, 0xc7, 0xa7, 0x60, 0x6e, 0x52, 0x97, 0x3c, - 0x85, 0xf4, 0x60, 0x46, 0x5a, 0x60, 0x59, 0x08, 0x39, 0x19, 0xed, 0x73, 0xeb, 0x80, - 0x5c, 0x11, 0x83, 0x01, + 0x1a, 0x02, 0xd2, 0x88, 0x78, 0x30, 0xe0, 0xb4, 0xb6, 0xdf, 0xe3, 0xcf, 0x65, 0x8d, + 0x2c, 0x04, 0x05, 0x20, 0x26, 0x4b, 0x38, 0x12, 0xaf, 0xd7, 0x9e, 0x13, 0xed, 0xfc, + 0xb2, 0x53, 0xd4, 0x39, ], ivk: [ - 0x76, 0xf4, 0x9c, 0xf8, 0xa3, 0x19, 0x21, 0x85, 0x61, 0x6a, 0x9a, 0x0d, 0xa0, 0xc7, - 0x6e, 0xc2, 0xc2, 0x75, 0x61, 0x59, 0xbc, 0xe1, 0x86, 0xa1, 0x86, 0x2b, 0x6e, 0x6e, - 0x59, 0x44, 0x2d, 0x11, + 0xa6, 0x1a, 0x67, 0x10, 0x00, 0x60, 0x14, 0x96, 0x42, 0xca, 0x66, 0x90, 0xd2, 0x4e, + 0x9f, 0xc3, 0x13, 0xa1, 0x82, 0x59, 0xdb, 0x73, 0x0a, 0x50, 0xd7, 0xe7, 0x58, 0xc5, + 0xd5, 0x44, 0xd0, 0x1d, ], ovk: [ - 0xeb, 0x72, 0xb6, 0xc3, 0x1e, 0x83, 0x7f, 0xd8, 0x37, 0xaa, 0xcb, 0x61, 0xfa, 0xba, - 0xce, 0x75, 0xa1, 0x9d, 0xd9, 0xdd, 0x5b, 0x4b, 0x3a, 0x3e, 0xe7, 0x23, 0xc1, 0x4d, - 0xa7, 0x7b, 0x4b, 0xe8, + 0x72, 0x7a, 0x52, 0x1e, 0xf1, 0xf9, 0x1c, 0x43, 0xf2, 0x17, 0xc4, 0x54, 0xc6, 0x41, + 0xb8, 0x3e, 0xc4, 0xb1, 0x66, 0x1a, 0x3c, 0xac, 0x0e, 0x3f, 0x74, 0xa7, 0x48, 0x0f, + 0xda, 0xaf, 0xad, 0x9f, ], dk: [ - 0xee, 0x19, 0xf8, 0xdd, 0xd9, 0xda, 0x06, 0x34, 0x24, 0x51, 0x43, 0xc4, 0xb4, 0x3a, - 0xfc, 0x7d, 0x78, 0xc5, 0x49, 0xc8, 0x20, 0x54, 0xa9, 0xd8, 0x40, 0x07, 0xb5, 0x62, - 0x17, 0xdb, 0xfd, 0xd6, + 0x20, 0x9d, 0xbb, 0x87, 0x11, 0xd9, 0xee, 0xef, 0x7f, 0x22, 0x0f, 0xd4, 0x28, 0x09, + 0xfb, 0xbb, 0x4c, 0x4b, 0x92, 0x65, 0xd1, 0x62, 0xdf, 0xf2, 0x36, 0x78, 0xca, 0xe7, + 0x70, 0x2b, 0xc5, 0x5e, ], default_d: [ - 0xaa, 0xe3, 0x6e, 0x09, 0x4d, 0xe0, 0x7b, 0xc1, 0x6f, 0x89, 0x8e, + 0xc5, 0x57, 0x04, 0x43, 0xf9, 0xc5, 0x17, 0xc5, 0x2b, 0x07, 0x68, ], default_pk_d: [ - 0xb6, 0x53, 0x3d, 0xcb, 0xff, 0xf0, 0xf6, 0xc1, 0xce, 0xef, 0xa8, 0x47, 0x99, 0xbd, - 0xa3, 0xde, 0x73, 0x34, 0x32, 0x6c, 0xcd, 0x65, 0xf7, 0xce, 0x92, 0xff, 0x3d, 0x9e, - 0x6e, 0x1f, 0x14, 0x0b, + 0xbd, 0x78, 0x5b, 0x8f, 0xa7, 0x56, 0x86, 0xd6, 0x9c, 0xd5, 0xaa, 0x5c, 0xb1, 0xff, + 0x1f, 0x58, 0xa1, 0x2d, 0x37, 0x75, 0x74, 0x28, 0x3a, 0xad, 0x1f, 0x06, 0xa9, 0xd9, + 0x63, 0x5e, 0x1d, 0x11, ], internal_rivk: [ - 0x25, 0x44, 0x06, 0x72, 0x3b, 0x06, 0x67, 0xaf, 0x27, 0xe5, 0x1c, 0xb3, 0xce, 0x8f, - 0xa1, 0x38, 0x81, 0x64, 0xd9, 0x43, 0x76, 0xc8, 0x50, 0xbd, 0xdb, 0x39, 0xe9, 0xbe, - 0xa5, 0xfa, 0x96, 0x05, + 0xd7, 0xcf, 0x88, 0xd8, 0xe7, 0xca, 0x57, 0x0e, 0x4a, 0xa2, 0x29, 0xbf, 0x82, 0x68, + 0x0d, 0x4d, 0xec, 0xb7, 0xcd, 0x05, 0xb6, 0x8e, 0x5c, 0x9c, 0x2b, 0xf1, 0x26, 0xba, + 0x6f, 0x41, 0x34, 0x3d, ], internal_ivk: [ - 0xba, 0xd4, 0x83, 0x7b, 0xa7, 0x88, 0x22, 0xb8, 0xb1, 0x65, 0xb0, 0xa1, 0x6e, 0x11, - 0x04, 0xc7, 0x05, 0xc3, 0xc0, 0xe3, 0x82, 0xd3, 0xf1, 0x3c, 0x19, 0x5c, 0x0e, 0xf3, - 0x11, 0xbb, 0x80, 0x04, + 0xc4, 0xd0, 0x70, 0xe8, 0x0e, 0x34, 0xb5, 0x03, 0x9f, 0x0d, 0xe6, 0x96, 0xb2, 0x11, + 0x35, 0x5f, 0x72, 0xc8, 0xf2, 0x52, 0xef, 0x81, 0xd0, 0xb7, 0x4c, 0xa1, 0xd1, 0x7b, + 0xed, 0x46, 0x4e, 0x1e, ], internal_ovk: [ - 0xb9, 0x11, 0x3a, 0x95, 0x2d, 0xcc, 0x1e, 0x15, 0xc3, 0x4d, 0x13, 0x66, 0x03, 0xa2, - 0xef, 0x25, 0x4a, 0x38, 0x75, 0x5a, 0x55, 0x7f, 0xa9, 0xf8, 0x8c, 0x14, 0x3b, 0xd3, - 0x07, 0x64, 0x41, 0xb0, + 0xeb, 0xc7, 0x26, 0x70, 0x3c, 0xc4, 0x93, 0xd8, 0x81, 0x68, 0xa6, 0x7c, 0xfb, 0xb1, + 0x95, 0xdd, 0xb7, 0x91, 0xff, 0x83, 0x19, 0x63, 0xd1, 0xcf, 0xe4, 0x24, 0xe5, 0x83, + 0x3a, 0x01, 0x1a, 0xa6, ], internal_dk: [ - 0x02, 0xb5, 0x2c, 0x6e, 0xd9, 0xad, 0x49, 0xfb, 0x38, 0xe4, 0x44, 0x7c, 0x69, 0xb5, - 0x70, 0xeb, 0xd0, 0x55, 0xe4, 0xc7, 0xfd, 0x91, 0xc0, 0x20, 0xff, 0x43, 0x46, 0x1d, - 0x14, 0xe0, 0x2f, 0x29, + 0x2a, 0xca, 0x74, 0x2a, 0x79, 0x77, 0xac, 0x71, 0xbd, 0x75, 0x5f, 0xd6, 0xb9, 0xe0, + 0x20, 0x70, 0x16, 0x74, 0x68, 0x88, 0x51, 0x4c, 0x52, 0x84, 0x0e, 0x58, 0xdb, 0xfc, + 0x6a, 0x3a, 0xd4, 0xc8, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 4079549063511228677, + note_v: 18438745196586160858, note_rho: [ - 0x26, 0x70, 0xdc, 0x82, 0xd3, 0x90, 0x26, 0xc6, 0xcb, 0x4c, 0xd4, 0xb0, 0xf7, 0xf5, - 0xaa, 0x2a, 0x4f, 0x5a, 0x53, 0x41, 0xec, 0x5d, 0xd7, 0x15, 0x40, 0x6f, 0x2f, 0xdd, - 0x2a, 0xfa, 0x73, 0x3f, + 0x1a, 0xbd, 0x5c, 0xe4, 0xfd, 0xdf, 0xcc, 0xfc, 0x3a, 0x61, 0x28, 0xae, 0xf7, 0x84, + 0xa6, 0x46, 0x10, 0xa8, 0x9d, 0x1a, 0x70, 0x99, 0x21, 0x6d, 0x08, 0x14, 0xd3, 0xa2, + 0xd4, 0x52, 0x43, 0x1c, ], note_rseed: [ - 0x5f, 0x64, 0x1c, 0x8c, 0x21, 0x86, 0x2a, 0x1b, 0xaf, 0xce, 0x26, 0x09, 0xd9, 0xee, - 0xcf, 0xa1, 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, - 0x83, 0x88, 0xe7, 0x6c, + 0x32, 0xd4, 0x11, 0xac, 0x1c, 0xce, 0x82, 0xad, 0x02, 0x29, 0x40, 0x7b, 0xbc, 0x48, + 0x98, 0x56, 0x75, 0xe3, 0xf8, 0x74, 0xa4, 0x53, 0x3f, 0x1d, 0x63, 0xa8, 0x4d, 0xfa, + 0x3e, 0x0f, 0x46, 0x0f, ], note_cmx: [ - 0x0f, 0xfb, 0xca, 0x1d, 0x59, 0x21, 0xfa, 0x0a, 0x8c, 0x51, 0x16, 0xae, 0x13, 0x7e, - 0x37, 0xf2, 0xc1, 0x18, 0xd5, 0x21, 0x25, 0x62, 0x8d, 0x8a, 0x3f, 0x41, 0x2c, 0xe0, - 0xe6, 0x53, 0x0e, 0x04, + 0x77, 0xb9, 0x90, 0x78, 0x30, 0x7c, 0x8b, 0x33, 0x0b, 0x74, 0xe1, 0x0e, 0x0a, 0xc9, + 0x02, 0x75, 0xfc, 0x9e, 0x46, 0x8c, 0xba, 0x67, 0x1c, 0x7c, 0xa2, 0xc5, 0xea, 0x12, + 0xfd, 0x8a, 0x45, 0x10, ], note_nf: [ - 0xe6, 0x2b, 0x8e, 0xd8, 0x35, 0x40, 0x14, 0x6c, 0xd2, 0x3c, 0xac, 0x74, 0xee, 0xd7, - 0xd7, 0x73, 0xd8, 0x02, 0x24, 0xa5, 0xaa, 0x30, 0xd6, 0x8e, 0x35, 0x57, 0x2e, 0xe8, - 0x83, 0xd1, 0xb7, 0x04, + 0x5b, 0xf6, 0xcf, 0x6f, 0xa6, 0xcf, 0x95, 0x17, 0x30, 0xe0, 0x23, 0x28, 0x8d, 0xaa, + 0xd0, 0xc6, 0x7c, 0x19, 0xab, 0xd7, 0xf7, 0xc9, 0x89, 0xfc, 0x8c, 0x56, 0xda, 0x15, + 0xa6, 0x08, 0x71, 0x08, ], }, TestVector { sk: [ - 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, 0xa9, 0x59, - 0xcc, 0x97, 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, - 0x9c, 0xfb, 0xdf, 0x73, + 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, 0x10, 0xd3, + 0xd0, 0x25, 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, + 0xba, 0x5d, 0x65, 0x7b, ], ask: [ - 0xf6, 0xef, 0x32, 0x8d, 0x24, 0x76, 0x1d, 0x6d, 0x3c, 0xcd, 0x25, 0xd4, 0x71, 0x96, - 0xe8, 0x10, 0x9c, 0x03, 0x8f, 0xe1, 0x7c, 0x59, 0xa7, 0xf0, 0x5b, 0x98, 0xd6, 0x6b, - 0xeb, 0xc6, 0x41, 0x24, + 0xca, 0xac, 0x7a, 0xe5, 0x49, 0x2d, 0x63, 0xe8, 0x88, 0xaa, 0xf3, 0x80, 0x5f, 0xcb, + 0x79, 0xae, 0x4a, 0xbc, 0x4a, 0xe1, 0x58, 0x4d, 0xf3, 0x85, 0x8b, 0xd4, 0xe3, 0x2a, + 0xd1, 0xc6, 0xbd, 0x14, ], ak: [ - 0xd1, 0x17, 0x87, 0xca, 0x58, 0x2f, 0x94, 0x8e, 0x45, 0x07, 0x18, 0xb3, 0x69, 0x98, - 0xdf, 0x28, 0xbb, 0x0f, 0x10, 0x21, 0xea, 0x84, 0x3f, 0x86, 0x7f, 0x8a, 0x17, 0x0f, - 0x5c, 0x33, 0x90, 0x1f, + 0xbc, 0x3c, 0x59, 0x11, 0x13, 0xdf, 0xd0, 0x29, 0x66, 0x3f, 0x03, 0x1c, 0xc1, 0x3f, + 0x7f, 0x94, 0xf4, 0x3c, 0x89, 0x8a, 0x79, 0x62, 0x90, 0x86, 0x11, 0x08, 0x99, 0xb2, + 0xb8, 0xe3, 0x3f, 0x13, + ], + isk: [ + 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, 0x8f, 0x4e, + 0x68, 0xf5, 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, + 0xc1, 0xec, 0x14, 0x4b, + ], + ik: [ + 0xe2, 0xb7, 0xd3, 0x28, 0x92, 0x52, 0xf8, 0x69, 0x17, 0xd4, 0xcb, 0x43, 0x04, 0xbe, + 0x9a, 0x06, 0xd6, 0x25, 0xdb, 0x6f, 0xb2, 0xcb, 0xea, 0xf8, 0x84, 0xc2, 0x80, 0x66, + 0x94, 0x16, 0xad, 0x30, ], nk: [ - 0x9e, 0x99, 0x7d, 0x9d, 0x26, 0x97, 0x87, 0x26, 0x8e, 0x09, 0x2a, 0x7c, 0x85, 0x41, - 0x7d, 0xa5, 0x30, 0xea, 0x42, 0xfa, 0xc6, 0x68, 0xa7, 0x49, 0xaf, 0x55, 0xdf, 0xb7, - 0x1c, 0xdb, 0xbe, 0x09, + 0x54, 0x81, 0x3a, 0x55, 0x4c, 0xd0, 0x88, 0xfd, 0xad, 0x77, 0x91, 0x00, 0xa5, 0xa4, + 0xe4, 0xb0, 0xec, 0x83, 0xd6, 0xc2, 0x8c, 0xa4, 0x8e, 0x0e, 0x6c, 0xd4, 0xc0, 0xae, + 0x3a, 0xec, 0x67, 0x1f, ], rivk: [ - 0x13, 0x6c, 0x6f, 0xe2, 0xe2, 0xb7, 0x9c, 0x51, 0x56, 0xdb, 0x50, 0x47, 0xd8, 0xd5, - 0xe7, 0x95, 0xdf, 0xc0, 0xbd, 0xc0, 0x88, 0x08, 0x53, 0xa4, 0x4a, 0xdb, 0x73, 0x92, - 0xc0, 0x2f, 0x94, 0x1b, + 0x7c, 0xa6, 0x44, 0x60, 0x34, 0x5e, 0xe1, 0x58, 0x8a, 0x1d, 0x68, 0xa5, 0x19, 0xcc, + 0x43, 0xf2, 0x04, 0xf9, 0xcc, 0x09, 0xf1, 0x5c, 0x67, 0x2b, 0x84, 0x26, 0x7b, 0xfd, + 0xd6, 0xfe, 0xba, 0x0f, ], ivk: [ - 0x02, 0x8b, 0x64, 0x05, 0x64, 0xb2, 0x49, 0x05, 0xde, 0x92, 0x92, 0xba, 0x5b, 0x98, - 0x10, 0xad, 0xdd, 0x86, 0xbe, 0xd0, 0xfb, 0x3b, 0x2d, 0x6b, 0x37, 0xf2, 0x6d, 0xd2, - 0x38, 0xa7, 0xdb, 0x13, + 0x1a, 0xc4, 0x6c, 0x8c, 0x2d, 0x85, 0xcd, 0xd1, 0x93, 0xd2, 0x19, 0xe2, 0x5b, 0x11, + 0xd8, 0xf8, 0xc7, 0x8a, 0x70, 0x29, 0x61, 0x40, 0x22, 0xfb, 0x6c, 0x48, 0x5f, 0x7a, + 0x79, 0x0b, 0xba, 0x3a, ], ovk: [ - 0x98, 0xd6, 0xa4, 0xbf, 0x68, 0x01, 0xd8, 0xba, 0x0d, 0x0b, 0x67, 0xea, 0x7b, 0x80, - 0x52, 0x07, 0xab, 0xc0, 0x34, 0x8f, 0xc5, 0x62, 0x00, 0x5a, 0x59, 0xa2, 0x7a, 0x8a, - 0x46, 0xfa, 0x6a, 0xdd, + 0xc8, 0x07, 0x3c, 0x0e, 0x75, 0xfb, 0x45, 0xc5, 0x4b, 0x17, 0x04, 0xa4, 0xe9, 0x4c, + 0x26, 0x78, 0xe2, 0xfb, 0x36, 0xea, 0xea, 0x1e, 0xd8, 0x48, 0xb2, 0x47, 0xaa, 0x25, + 0x2f, 0xa5, 0x05, 0x86, ], dk: [ - 0xd0, 0xba, 0xef, 0x60, 0x12, 0xd3, 0x08, 0xef, 0xbb, 0x76, 0x9a, 0x99, 0xcc, 0xa2, - 0x92, 0x8c, 0xed, 0xe8, 0xdb, 0x27, 0x76, 0x45, 0xa7, 0x77, 0xea, 0xf1, 0x72, 0x2c, - 0xd0, 0x84, 0x50, 0xb3, + 0x78, 0x2a, 0xb8, 0xbe, 0x6d, 0x3b, 0x74, 0x03, 0x62, 0x12, 0xe5, 0xea, 0xc8, 0x95, + 0x7f, 0xc4, 0x85, 0x6a, 0x4d, 0xd0, 0x4b, 0x60, 0x71, 0xa0, 0x55, 0x13, 0xa8, 0x6b, + 0x35, 0x05, 0xfb, 0x8f, ], default_d: [ - 0xcc, 0x7c, 0xe7, 0x34, 0xb0, 0x75, 0xa0, 0x1b, 0x92, 0xaa, 0xca, + 0xba, 0x03, 0xdb, 0x92, 0xca, 0xb9, 0x1d, 0x77, 0xfb, 0xff, 0x92, ], default_pk_d: [ - 0x3d, 0xa5, 0x27, 0x3a, 0x56, 0x67, 0xc7, 0x66, 0xb8, 0x23, 0x12, 0x06, 0x18, 0x0f, - 0x15, 0x8a, 0xc0, 0x2a, 0xf3, 0xf0, 0x6e, 0xcc, 0xa6, 0xec, 0x7c, 0x38, 0xc7, 0x5d, - 0x33, 0x60, 0x03, 0x20, + 0x5e, 0x25, 0x56, 0xeb, 0x74, 0x70, 0x78, 0x26, 0x3b, 0x4d, 0xb4, 0xba, 0xc7, 0xf8, + 0x56, 0xe0, 0x66, 0x1b, 0x04, 0xed, 0xc6, 0x14, 0xb4, 0xeb, 0xd4, 0x96, 0x45, 0xf7, + 0x63, 0xd3, 0x23, 0x86, ], internal_rivk: [ - 0x88, 0xd7, 0xb1, 0x96, 0x99, 0xf3, 0x94, 0xa5, 0x50, 0xbc, 0x9c, 0xdc, 0x6b, 0xf3, - 0xfc, 0x71, 0xf6, 0x10, 0xc3, 0x06, 0x56, 0x37, 0x61, 0x53, 0xa6, 0x96, 0x1f, 0xcd, - 0x5b, 0x97, 0xfa, 0x19, + 0xb9, 0xcc, 0x87, 0xef, 0x06, 0x4f, 0x87, 0xff, 0xe5, 0xd3, 0xc2, 0x3b, 0x69, 0x44, + 0x9e, 0x44, 0x6b, 0x21, 0x33, 0x3e, 0xe0, 0x39, 0x04, 0xad, 0xca, 0xb1, 0x6f, 0x05, + 0x15, 0xee, 0x78, 0x07, ], internal_ivk: [ - 0x0a, 0x2d, 0xc9, 0x66, 0x61, 0xb9, 0x27, 0x25, 0x0d, 0x7e, 0x3c, 0xd2, 0xc7, 0xe0, - 0x6d, 0x51, 0x74, 0xc6, 0x2c, 0xb1, 0x2e, 0x07, 0x16, 0x7f, 0x19, 0x4f, 0x4c, 0xe6, - 0x4e, 0x68, 0x95, 0x02, + 0x44, 0x35, 0x8f, 0x75, 0xda, 0x3a, 0x1d, 0xd9, 0xa2, 0xa2, 0xb0, 0x7c, 0x0b, 0x4e, + 0x2f, 0xc2, 0x01, 0x89, 0xd9, 0xfc, 0x3d, 0x0d, 0x8a, 0xae, 0xf8, 0x93, 0xfe, 0xed, + 0xae, 0x57, 0x26, 0x29, ], internal_ovk: [ - 0xcc, 0x79, 0x65, 0xf3, 0x3a, 0xc0, 0x1c, 0x60, 0x68, 0x51, 0xb1, 0x29, 0xbd, 0xc9, - 0xb6, 0xab, 0xd5, 0xca, 0x5b, 0x9d, 0x24, 0x1d, 0xbd, 0x5c, 0x18, 0xb2, 0x46, 0x9b, - 0x7c, 0x8c, 0xc8, 0x9f, + 0xb5, 0xea, 0x50, 0xd3, 0xe5, 0xcd, 0x42, 0x99, 0x63, 0x30, 0xfb, 0xa6, 0xb8, 0x52, + 0x3e, 0xf8, 0x12, 0x26, 0x5b, 0x4b, 0xa4, 0x32, 0x58, 0x1c, 0x21, 0x03, 0xe3, 0x52, + 0xd1, 0x6d, 0xbb, 0x90, ], internal_dk: [ - 0xda, 0xa2, 0x42, 0xd2, 0x0d, 0xfd, 0xce, 0x8f, 0xc1, 0x0f, 0x4d, 0x99, 0x39, 0x7d, - 0xa2, 0x2c, 0x49, 0x1d, 0xc0, 0x9e, 0x1b, 0x12, 0x0f, 0x66, 0x93, 0xd6, 0x86, 0xec, - 0xd4, 0x03, 0x0a, 0x00, + 0xdd, 0x13, 0xbb, 0x22, 0x13, 0x80, 0x96, 0xc7, 0xaf, 0x9a, 0x16, 0x98, 0x88, 0x4d, + 0x3d, 0xe8, 0x96, 0x06, 0x48, 0xf8, 0x74, 0xf9, 0x42, 0x22, 0xbd, 0x76, 0xb7, 0x67, + 0x82, 0x5e, 0x5d, 0xb6, + ], + asset: [ + 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, + 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, + 0x90, 0x5a, 0xae, 0x08, ], - note_v: 5706402952489856202, + note_v: 1456989545392107075, note_rho: [ - 0xa1, 0xdf, 0x0e, 0x5b, 0x87, 0xb5, 0xbe, 0xce, 0x47, 0x7a, 0x70, 0x96, 0x49, 0xe9, - 0x50, 0x06, 0x05, 0x91, 0x39, 0x48, 0x12, 0x95, 0x1e, 0x1f, 0xe3, 0x89, 0x5b, 0x8c, - 0xc3, 0xd1, 0x4d, 0x2c, + 0x90, 0x70, 0x46, 0x07, 0xf3, 0x87, 0xa0, 0x3e, 0x49, 0xbf, 0x98, 0x36, 0x57, 0x44, + 0x31, 0x34, 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, + 0x62, 0xcb, 0x78, 0x0a, ], note_rseed: [ - 0xf6, 0x55, 0x6d, 0xf6, 0xed, 0x4b, 0x4d, 0xdd, 0x3d, 0x9a, 0x69, 0xf5, 0x33, 0x57, - 0xd7, 0x76, 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, - 0xcd, 0x08, 0xcb, 0x05, + 0xb6, 0x88, 0x3a, 0x50, 0xa0, 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, + 0x82, 0x84, 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, + 0x0d, 0xc0, 0xb7, 0x16, ], note_cmx: [ - 0x63, 0xce, 0xe3, 0x7e, 0x3c, 0x7b, 0x4e, 0x6c, 0xc9, 0x39, 0xa2, 0xe6, 0x3a, 0xda, - 0x74, 0xf8, 0x5e, 0xa4, 0x8b, 0xa0, 0x7a, 0x4f, 0x92, 0xcc, 0xbd, 0x34, 0xfa, 0xa4, - 0x2d, 0xfd, 0x49, 0x16, + 0x38, 0x14, 0x8e, 0x9e, 0x3b, 0x05, 0x3a, 0x6d, 0x8f, 0xa7, 0x86, 0x07, 0xed, 0x57, + 0x64, 0x75, 0x83, 0xa7, 0xf9, 0x37, 0x55, 0x38, 0x84, 0x7b, 0x8c, 0x4a, 0xa0, 0xb4, + 0xeb, 0x43, 0xa7, 0x32, ], note_nf: [ - 0x4c, 0x99, 0xbf, 0xa8, 0xc2, 0x0d, 0xba, 0x59, 0xbb, 0x73, 0x47, 0xda, 0x16, 0xc4, - 0x3b, 0x73, 0xc8, 0x87, 0x94, 0xc9, 0xeb, 0xcd, 0x0d, 0xd2, 0xb2, 0x5e, 0xe7, 0xbb, - 0x83, 0x6f, 0x95, 0x20, + 0x37, 0x57, 0x49, 0xa6, 0xa1, 0xd6, 0x44, 0xa4, 0x83, 0xc7, 0x09, 0xee, 0xc4, 0xaa, + 0x87, 0xb8, 0x58, 0xba, 0x0f, 0x71, 0x1b, 0x76, 0x5b, 0xbf, 0xfa, 0x97, 0xa9, 0x3f, + 0x57, 0x4f, 0x29, 0x23, ], }, TestVector { sk: [ - 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, 0x71, 0x62, - 0x69, 0xb9, 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, - 0x9e, 0x68, 0x62, 0x5a, + 0x03, 0xfd, 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, + 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, + 0x64, 0x0a, 0x69, 0x30, ], ask: [ - 0x75, 0x7d, 0x15, 0x8d, 0x07, 0x35, 0x6b, 0x3b, 0xc2, 0xc9, 0xe5, 0x1c, 0x55, 0x8a, - 0x9b, 0x31, 0x6b, 0xdd, 0xbc, 0x36, 0x0b, 0x8b, 0xeb, 0x6e, 0x2a, 0xe3, 0xb0, 0x61, - 0x8f, 0x06, 0x2d, 0x2e, + 0xd0, 0xa8, 0x8e, 0x38, 0xe2, 0xd6, 0x67, 0x96, 0xf4, 0x9f, 0x9f, 0x39, 0x48, 0x44, + 0xa3, 0x1e, 0x29, 0x02, 0xa4, 0x14, 0x0a, 0xbf, 0x96, 0x9d, 0x5a, 0x6a, 0x39, 0xd0, + 0xbe, 0x92, 0x16, 0x21, ], ak: [ - 0x44, 0x9a, 0x90, 0xd2, 0xe8, 0xd1, 0xa0, 0x37, 0x64, 0x2a, 0x97, 0x09, 0x6c, 0x91, - 0x65, 0x43, 0x46, 0x2a, 0x13, 0x7f, 0xfe, 0xa3, 0x7b, 0xaf, 0x41, 0xef, 0x28, 0x6b, - 0xb7, 0x32, 0xbe, 0x2c, + 0xb6, 0xd5, 0x12, 0x34, 0xfe, 0xf8, 0x7c, 0xaf, 0x48, 0x38, 0x54, 0x07, 0xeb, 0x1d, + 0x32, 0x71, 0xf9, 0xad, 0xc7, 0x1d, 0xe7, 0xc0, 0x81, 0xca, 0x6a, 0xae, 0xc0, 0xf9, + 0x18, 0x4f, 0x0c, 0x2a, + ], + isk: [ + 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, 0xd3, 0xf4, 0x1e, 0x72, + 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, + 0x07, 0x39, 0xf0, 0x53, + ], + ik: [ + 0x03, 0xd8, 0x30, 0x92, 0xd7, 0x09, 0xcb, 0x92, 0x8f, 0xf1, 0x50, 0xf0, 0x8e, 0xa2, + 0x68, 0xe8, 0x45, 0x41, 0x80, 0xcd, 0xc4, 0x9f, 0x07, 0xf5, 0xa3, 0xd9, 0xb2, 0x03, + 0x90, 0x68, 0xc9, 0x09, ], nk: [ - 0xfd, 0x31, 0x64, 0xc6, 0x32, 0xbe, 0xc9, 0x4c, 0xe9, 0xfb, 0x2f, 0x30, 0x22, 0x63, - 0xb8, 0x84, 0xab, 0xb9, 0xc1, 0x0e, 0x55, 0xe4, 0x48, 0x64, 0x7f, 0x67, 0x98, 0x49, - 0x5c, 0x9d, 0x08, 0x3f, + 0x0d, 0x47, 0x60, 0xf0, 0xe9, 0x3d, 0x2c, 0x4b, 0x67, 0x6e, 0x88, 0xfa, 0x40, 0xfa, + 0x8d, 0xb7, 0x1b, 0xb6, 0x5d, 0x49, 0xa3, 0xa0, 0xc4, 0x6f, 0xa7, 0xa2, 0xef, 0x14, + 0x68, 0x42, 0x2b, 0x01, ], rivk: [ - 0xc0, 0xb3, 0x6b, 0x56, 0x07, 0x0f, 0xff, 0x2f, 0xdf, 0x38, 0xeb, 0xa1, 0x1a, 0x74, - 0x24, 0x95, 0x71, 0x95, 0x01, 0x4c, 0xba, 0x43, 0xa5, 0x6b, 0xd1, 0xb1, 0x65, 0x8e, - 0x66, 0xa3, 0x9d, 0x00, + 0xd4, 0x2b, 0x9a, 0x02, 0x8a, 0xbb, 0xe3, 0x86, 0x43, 0x77, 0x48, 0xdb, 0x20, 0x9f, + 0xdb, 0xa8, 0x40, 0xf3, 0xf6, 0x82, 0xa5, 0x0c, 0x1e, 0xf0, 0xaf, 0xa4, 0xa9, 0xfe, + 0x7b, 0xa3, 0x3f, 0x2b, ], ivk: [ - 0x97, 0x6a, 0x87, 0x88, 0x19, 0x1b, 0x87, 0xe4, 0xc1, 0x3f, 0x2c, 0x6d, 0x23, 0xb4, - 0xf3, 0x59, 0x5e, 0x02, 0x28, 0xe2, 0x45, 0xe9, 0x6e, 0xef, 0x1d, 0x24, 0xb2, 0x93, - 0x29, 0x6a, 0x19, 0x1c, + 0xec, 0x8d, 0x1b, 0x93, 0x18, 0x3d, 0x20, 0x33, 0xc2, 0x7b, 0x18, 0xe8, 0xc8, 0xbc, + 0xe1, 0xa0, 0xc2, 0xcd, 0x49, 0x7a, 0x35, 0x84, 0xf1, 0x6e, 0x3b, 0x90, 0x79, 0xc9, + 0xa9, 0x33, 0x50, 0x27, ], ovk: [ - 0x1e, 0xd0, 0xed, 0xa5, 0xa4, 0x08, 0x61, 0x31, 0x26, 0x1a, 0x2e, 0xd4, 0x42, 0x92, - 0x61, 0xe4, 0x27, 0x6a, 0x26, 0xd4, 0x28, 0x59, 0xfa, 0xbd, 0xa3, 0x1a, 0xa9, 0x67, - 0x09, 0x87, 0x43, 0x71, + 0x2f, 0x84, 0x6f, 0xbb, 0x28, 0xfb, 0x64, 0x2c, 0x43, 0x0a, 0x2b, 0xef, 0x8c, 0xb1, + 0xde, 0x58, 0x95, 0x2d, 0xa6, 0x22, 0xe5, 0x89, 0x38, 0xab, 0xaf, 0x10, 0xa6, 0x92, + 0x9a, 0x7f, 0xa1, 0xee, ], dk: [ - 0x5e, 0x5b, 0x60, 0xc0, 0x5b, 0x53, 0xd0, 0xbc, 0xd2, 0xda, 0x46, 0xa1, 0x31, 0x29, - 0x12, 0x51, 0x5c, 0xc7, 0xcf, 0x2d, 0x97, 0x4c, 0x11, 0x7c, 0x8d, 0xde, 0xa9, 0xfa, - 0xb6, 0x20, 0xc6, 0x68, + 0x7b, 0xf1, 0x6e, 0xcf, 0x21, 0x0e, 0xb5, 0x19, 0x02, 0xb4, 0x99, 0xd6, 0xbc, 0x5c, + 0xab, 0xb0, 0x77, 0x17, 0x64, 0x1a, 0xd4, 0xb0, 0x1a, 0xa5, 0x08, 0xac, 0x93, 0x11, + 0x0b, 0x36, 0x0c, 0x2c, ], default_d: [ - 0x99, 0xaf, 0x6b, 0xf3, 0xf4, 0x75, 0xbd, 0xe8, 0x89, 0xaa, 0xca, + 0x49, 0xa0, 0xd1, 0xfa, 0x5b, 0x94, 0x5d, 0xd7, 0xb6, 0xc6, 0x64, ], default_pk_d: [ - 0xac, 0xdc, 0xd3, 0x48, 0xca, 0x45, 0xee, 0x58, 0x32, 0x78, 0x30, 0x38, 0x46, 0xca, - 0x07, 0x84, 0x59, 0xd5, 0xbe, 0x5c, 0x5d, 0xcf, 0x34, 0x7e, 0x3b, 0x9a, 0x34, 0xcb, - 0xa1, 0x24, 0xb4, 0xa3, + 0x56, 0xfd, 0x76, 0xdd, 0x5b, 0xb7, 0x44, 0xa9, 0x49, 0x4c, 0x08, 0xed, 0x92, 0xda, + 0x2c, 0xf3, 0xd7, 0x48, 0x44, 0x34, 0xc9, 0x54, 0x59, 0x23, 0xf3, 0x82, 0x1a, 0xcc, + 0x01, 0x32, 0x17, 0x1a, ], internal_rivk: [ - 0x94, 0x1a, 0x17, 0xe1, 0x20, 0x2a, 0x62, 0x71, 0xa4, 0x4a, 0x01, 0x66, 0x65, 0x53, - 0xb5, 0x81, 0xbf, 0x25, 0xef, 0x99, 0xe8, 0xe9, 0x5f, 0x13, 0x2a, 0xce, 0x38, 0x1d, - 0x96, 0x01, 0x84, 0x32, + 0xcb, 0x53, 0x0d, 0x7b, 0x34, 0xfb, 0x08, 0x9c, 0x92, 0x72, 0x1c, 0x3e, 0xa0, 0xd2, + 0x14, 0x4d, 0x87, 0xb8, 0x9c, 0xa0, 0xc0, 0x6a, 0x9d, 0x44, 0x6d, 0x88, 0x1f, 0x4a, + 0x99, 0xa1, 0xf9, 0x33, ], internal_ivk: [ - 0xa2, 0x76, 0x29, 0xac, 0x1c, 0x62, 0xc9, 0xf4, 0xda, 0xd5, 0x7c, 0x95, 0x30, 0xab, - 0x2a, 0x59, 0x80, 0x0d, 0x2e, 0xf4, 0x55, 0xcd, 0x17, 0x44, 0x6f, 0x3f, 0xc6, 0x08, - 0x1a, 0x58, 0x1e, 0x3b, + 0xda, 0x1d, 0x87, 0xca, 0x7d, 0xf0, 0xf3, 0x9b, 0x24, 0xfc, 0x8f, 0x50, 0xa3, 0x05, + 0xd8, 0x3a, 0x03, 0xce, 0xba, 0x2a, 0x59, 0xd2, 0x7a, 0x7d, 0xd4, 0x01, 0x34, 0x05, + 0x18, 0x40, 0x18, 0x25, ], internal_ovk: [ - 0xe9, 0x89, 0x8e, 0xd6, 0xb6, 0x69, 0xc8, 0xd9, 0xd5, 0x90, 0xb7, 0x59, 0xd0, 0x29, - 0x5f, 0xcf, 0xaf, 0x95, 0xe2, 0xda, 0xf7, 0xda, 0x99, 0x1c, 0x27, 0x57, 0xdc, 0xef, - 0xe1, 0x62, 0x6e, 0x0e, + 0x87, 0x66, 0x9c, 0x4e, 0x89, 0xf6, 0x8e, 0x3c, 0xe9, 0x60, 0x6e, 0xe7, 0x26, 0x52, + 0xb3, 0x89, 0x3d, 0xff, 0x01, 0x3f, 0x71, 0x89, 0x8f, 0x77, 0x82, 0x40, 0x4f, 0xba, + 0x8c, 0xef, 0x40, 0x3a, ], internal_dk: [ - 0x61, 0x0c, 0xbd, 0x9a, 0x57, 0x79, 0x79, 0xe1, 0xf7, 0x1d, 0xa8, 0x10, 0x0f, 0x6f, - 0xe6, 0xb8, 0xf6, 0xd1, 0x0a, 0x74, 0x7f, 0xed, 0x2a, 0x1c, 0x91, 0xcb, 0xe1, 0x42, - 0x47, 0x5c, 0x30, 0x82, + 0x24, 0x5c, 0xf8, 0xf2, 0xe0, 0x54, 0xb1, 0xc0, 0x3b, 0x5f, 0x19, 0xf6, 0xd2, 0x9d, + 0x15, 0x69, 0x6f, 0x0f, 0x1d, 0x39, 0x21, 0xf6, 0xcf, 0x1d, 0x6f, 0x5f, 0x8f, 0xd5, + 0xd6, 0x61, 0x46, 0x50, + ], + asset: [ + 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, + 0x41, 0x87, 0x2c, 0xfc, 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, + 0x3d, 0xbf, 0xf9, 0x30, ], - note_v: 2558469029534639129, + note_v: 10781511188385845786, note_rho: [ - 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, 0x2e, 0x19, - 0xe5, 0x94, 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, - 0x10, 0xd3, 0xd0, 0x25, + 0x7a, 0xe3, 0x5a, 0xf7, 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, + 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, + 0x2e, 0x65, 0x0b, 0x38, ], note_rseed: [ - 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, 0xba, 0x5d, - 0x65, 0x7b, 0x43, 0xee, 0x8d, 0xa6, 0x45, 0x44, 0x38, 0x14, 0xcc, 0x73, 0x29, 0xf3, - 0xe9, 0xb4, 0xe5, 0x4c, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, ], note_cmx: [ - 0x1e, 0x61, 0x9e, 0x46, 0xbb, 0x62, 0xb6, 0x1d, 0x4e, 0x1c, 0xf3, 0x62, 0x2e, 0xa7, - 0x0a, 0x90, 0x8d, 0xe7, 0xf0, 0x76, 0xec, 0xf8, 0x7f, 0x54, 0x1e, 0x0b, 0x7b, 0x48, - 0xad, 0x4a, 0x26, 0x01, + 0xbe, 0xe1, 0xae, 0x8e, 0x13, 0xef, 0x9b, 0xda, 0x15, 0x3f, 0xa2, 0xde, 0xf1, 0xf7, + 0x23, 0x97, 0xa1, 0xce, 0xd9, 0x5f, 0x1d, 0x2a, 0x9f, 0x96, 0xfb, 0x09, 0x77, 0x5f, + 0x86, 0x7f, 0x7c, 0x32, ], note_nf: [ - 0x3b, 0x94, 0x8d, 0xb2, 0x16, 0x08, 0xe9, 0xac, 0xb2, 0x2a, 0x54, 0x17, 0xb9, 0x8c, - 0x0d, 0xed, 0xd5, 0x27, 0xa9, 0x64, 0x87, 0x81, 0x4e, 0x64, 0x20, 0xcb, 0xff, 0x6e, - 0x4e, 0xee, 0x4e, 0x31, + 0x46, 0xca, 0xbd, 0x45, 0x05, 0xe6, 0xf4, 0xf8, 0x6d, 0x2a, 0xa4, 0xbe, 0x6b, 0x14, + 0x61, 0x3a, 0xca, 0xa4, 0x13, 0x33, 0x34, 0x44, 0xcf, 0x3e, 0x48, 0x5e, 0x6b, 0xeb, + 0x39, 0xf2, 0xa7, 0x27, ], }, TestVector { sk: [ - 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, - 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, 0x86, 0xa2, 0x65, 0x8e, 0x0a, 0x07, 0xa0, 0x5a, - 0xc5, 0xb9, 0x50, 0x05, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, ], ask: [ - 0xb4, 0xde, 0xd9, 0x0d, 0x62, 0x11, 0x7f, 0x18, 0xf3, 0xdd, 0x5f, 0xdb, 0x22, 0x23, - 0x8a, 0x35, 0xca, 0x37, 0xc4, 0x0f, 0xee, 0xc8, 0x45, 0xce, 0x5f, 0xc2, 0x7f, 0xe8, - 0xbc, 0xa5, 0xef, 0x0f, + 0x71, 0x37, 0xb4, 0x05, 0xf0, 0x52, 0x86, 0xe8, 0xf2, 0x77, 0x0c, 0xd2, 0x1e, 0x2f, + 0x2c, 0x15, 0x28, 0x76, 0x4d, 0x4a, 0xad, 0x93, 0x85, 0x04, 0x0e, 0xa2, 0xec, 0x74, + 0xaa, 0x6e, 0xa6, 0x31, ], ak: [ - 0x4e, 0xfd, 0x5a, 0x2e, 0xf1, 0xff, 0xa9, 0x9a, 0x0f, 0xf6, 0x2b, 0x76, 0x7d, 0x44, - 0xb3, 0x65, 0x1f, 0xfa, 0x1c, 0x69, 0x69, 0x15, 0xac, 0x00, 0xa2, 0x5e, 0xa3, 0xac, - 0x7d, 0xff, 0x99, 0x01, + 0x78, 0xdb, 0xcc, 0x02, 0x0e, 0x1b, 0xbc, 0xe5, 0x4d, 0x0f, 0x54, 0x76, 0xa6, 0x64, + 0x3b, 0xc8, 0x2d, 0xae, 0x3e, 0x61, 0x4a, 0xc5, 0x8d, 0x05, 0x7f, 0xfc, 0x5d, 0x3c, + 0x60, 0xd7, 0x5e, 0x3e, + ], + isk: [ + 0x60, 0xfe, 0x49, 0xe3, 0x7e, 0x4f, 0x66, 0x69, 0x31, 0x67, 0x73, 0x19, 0xed, 0x89, + 0xf8, 0x55, 0x88, 0x74, 0x1b, 0x31, 0x28, 0x90, 0x1a, 0x93, 0xbd, 0x78, 0xe4, 0xbe, + 0x02, 0x25, 0xa9, 0xe2, + ], + ik: [ + 0x78, 0xfe, 0x62, 0x0f, 0xc5, 0x91, 0x3f, 0xc1, 0x8a, 0xa2, 0x09, 0x36, 0x40, 0x9d, + 0x38, 0x8f, 0x0f, 0x10, 0x88, 0x14, 0xa7, 0x5e, 0x93, 0x1b, 0xea, 0xcb, 0x61, 0x83, + 0xa9, 0xbe, 0x18, 0xc4, ], nk: [ - 0x02, 0xab, 0x99, 0x5c, 0xe9, 0x8f, 0x63, 0x02, 0x5f, 0xb6, 0x24, 0x28, 0xa0, 0xfb, - 0xf5, 0x2f, 0x25, 0x22, 0xe6, 0xa2, 0x72, 0x61, 0x07, 0x8a, 0x9f, 0x4d, 0x6a, 0x36, - 0xa1, 0xc0, 0x5d, 0x39, + 0x88, 0xc5, 0xc9, 0x2d, 0x1c, 0xd0, 0xe5, 0x01, 0xc9, 0x1d, 0x80, 0x1c, 0x50, 0xdf, + 0x26, 0xd3, 0xbb, 0xbc, 0x5f, 0x7c, 0xc0, 0x49, 0xcb, 0xb2, 0x9d, 0xc3, 0x80, 0x17, + 0x85, 0x6f, 0xbb, 0x10, ], rivk: [ - 0xd9, 0x84, 0x0d, 0x0b, 0xd8, 0x95, 0x20, 0xab, 0xbc, 0xa7, 0xf1, 0x0b, 0xe6, 0xeb, - 0xa3, 0x66, 0xf8, 0x6e, 0xc3, 0xb7, 0x8d, 0xbd, 0xf1, 0xeb, 0xfe, 0x20, 0xd9, 0x95, - 0x12, 0xaf, 0x15, 0x15, + 0x7e, 0xc2, 0xbb, 0xc2, 0xe8, 0x1c, 0x38, 0x95, 0xe2, 0x3c, 0x74, 0x14, 0x3c, 0x52, + 0xce, 0x83, 0xde, 0xf8, 0x7d, 0xb0, 0xa7, 0x03, 0x94, 0xf7, 0xba, 0xa0, 0x70, 0x0f, + 0xce, 0x23, 0x43, 0x11, ], ivk: [ - 0x58, 0xf5, 0xbb, 0x5c, 0x32, 0x31, 0x15, 0x25, 0x29, 0x42, 0x3b, 0x67, 0xfa, 0x43, - 0x28, 0x79, 0x11, 0x26, 0x35, 0xcd, 0xa0, 0xda, 0x2e, 0xc2, 0x41, 0x9c, 0x6f, 0xe9, - 0x1e, 0xa4, 0x8d, 0x24, + 0xdd, 0x92, 0x93, 0xed, 0x12, 0x10, 0x4c, 0x31, 0xd7, 0xa1, 0x2a, 0xbd, 0xd3, 0xcf, + 0x19, 0x56, 0x93, 0x93, 0x66, 0x84, 0x4c, 0x8a, 0x07, 0xf5, 0x08, 0x34, 0xa5, 0x86, + 0x15, 0x5b, 0xc2, 0x1a, ], ovk: [ - 0x78, 0xf5, 0xd3, 0x48, 0x67, 0x2e, 0x8d, 0x20, 0x9c, 0x41, 0xb7, 0x83, 0xf8, 0xca, - 0x14, 0xa7, 0x7b, 0x3e, 0xa3, 0xe6, 0x00, 0x4c, 0xa4, 0xe0, 0xc2, 0x5a, 0xa4, 0x45, - 0x63, 0x98, 0x1d, 0xcb, + 0xb5, 0xfc, 0x70, 0xd4, 0xee, 0x1b, 0x52, 0x8e, 0x20, 0xd0, 0xee, 0x81, 0x6e, 0x84, + 0x5e, 0xf8, 0x9c, 0x2c, 0xf4, 0x31, 0xa3, 0x18, 0x27, 0x22, 0xfd, 0xe8, 0xbb, 0x37, + 0x39, 0xc6, 0xd6, 0xac, ], dk: [ - 0x5d, 0x7f, 0xe3, 0x96, 0xbb, 0xfd, 0x22, 0x67, 0xac, 0xa7, 0x11, 0xab, 0x5b, 0x3e, - 0x1f, 0x02, 0x4f, 0x49, 0x11, 0xf3, 0xa1, 0x81, 0x73, 0x2f, 0x13, 0x22, 0xa1, 0x59, - 0x2f, 0x9e, 0x0e, 0xbe, + 0xc8, 0x57, 0x68, 0x3f, 0xfd, 0xc4, 0x6f, 0x1e, 0xf4, 0x01, 0xc0, 0x72, 0xae, 0xa0, + 0x23, 0x49, 0xa7, 0x75, 0xee, 0xe5, 0x5a, 0x5a, 0xad, 0x7b, 0x39, 0xda, 0xc9, 0xb1, + 0x07, 0x1f, 0x78, 0x2c, ], default_d: [ - 0x2f, 0xbe, 0x4b, 0x4b, 0x1e, 0xdf, 0xf3, 0x31, 0x23, 0xce, 0x65, + 0x2b, 0xc6, 0x0b, 0xe6, 0x02, 0x99, 0x36, 0x8b, 0x00, 0x6b, 0xf1, ], default_pk_d: [ - 0xeb, 0x2c, 0x6f, 0xee, 0x34, 0x1e, 0xad, 0xe0, 0x7d, 0x74, 0x87, 0x99, 0x7a, 0xa7, - 0x23, 0x69, 0x7d, 0x05, 0xe6, 0x29, 0x60, 0xdf, 0x37, 0x9c, 0x9e, 0x4a, 0x8d, 0x47, - 0x6d, 0xfa, 0xc5, 0xbf, + 0x88, 0x44, 0x53, 0xc6, 0x20, 0x2f, 0x5b, 0xda, 0x5b, 0x3c, 0xb7, 0xc1, 0x19, 0x35, + 0x1a, 0x4b, 0x7d, 0x27, 0x77, 0x7a, 0xf3, 0x75, 0x1b, 0xe6, 0x93, 0x33, 0x4a, 0x7d, + 0xcd, 0x62, 0x86, 0x14, ], internal_rivk: [ - 0x66, 0x3b, 0x67, 0xd3, 0xac, 0x15, 0x99, 0x27, 0xf0, 0x6e, 0x6c, 0x8d, 0xab, 0x80, - 0xa5, 0x89, 0x67, 0xc5, 0x45, 0xda, 0xac, 0x3d, 0x98, 0x72, 0x9a, 0x0b, 0xcc, 0x41, - 0xfd, 0x53, 0x6d, 0x2b, + 0x7a, 0x20, 0x92, 0x16, 0xf7, 0x8a, 0x6d, 0xd5, 0x0d, 0x5a, 0xc2, 0x20, 0x8a, 0x39, + 0xa7, 0x0b, 0xa2, 0x80, 0x71, 0xd1, 0xdf, 0x72, 0x62, 0xb6, 0x27, 0x93, 0x44, 0x49, + 0x10, 0x24, 0xa3, 0x31, ], internal_ivk: [ - 0xaa, 0x6a, 0xcc, 0x8a, 0x7a, 0xa9, 0xa8, 0x05, 0x20, 0x04, 0xff, 0x93, 0x83, 0x3f, - 0x4a, 0xbb, 0x15, 0x3b, 0x45, 0x79, 0x7f, 0xd9, 0x07, 0xe3, 0x05, 0xc8, 0x92, 0x7b, - 0xb0, 0x37, 0x82, 0x20, + 0xf9, 0xb9, 0xd0, 0xd3, 0xe5, 0x30, 0xe2, 0x69, 0x9a, 0xdc, 0x7b, 0x3e, 0xbf, 0xd8, + 0x13, 0x9f, 0x0e, 0xf2, 0x1e, 0x5c, 0x10, 0x03, 0xc0, 0xd1, 0x1b, 0x8a, 0x8b, 0x47, + 0x93, 0xce, 0x00, 0x24, ], internal_ovk: [ - 0xbf, 0xd1, 0x09, 0x67, 0x27, 0xb6, 0xd5, 0xa2, 0xe1, 0x7a, 0xcb, 0xc5, 0xb2, 0x46, - 0x80, 0xcb, 0x88, 0xdb, 0x34, 0xcf, 0x53, 0xb6, 0xb7, 0x46, 0x6c, 0xef, 0x67, 0x6f, - 0xb3, 0xf7, 0x22, 0x29, + 0xa9, 0x6e, 0x11, 0xc5, 0x27, 0x11, 0xbf, 0x38, 0xee, 0x29, 0xd1, 0xc4, 0xb5, 0xa4, + 0x20, 0xbf, 0x83, 0x7c, 0x2a, 0x95, 0xc0, 0xaf, 0x5e, 0xa8, 0x83, 0xfb, 0x74, 0x74, + 0xca, 0xe6, 0xad, 0x9f, ], internal_dk: [ - 0x47, 0xbd, 0xf9, 0x27, 0x1e, 0xcc, 0x50, 0xe7, 0x05, 0xc5, 0x21, 0xcd, 0x0d, 0xbb, - 0xaf, 0x1c, 0x4e, 0x6a, 0x96, 0x2f, 0xc9, 0x14, 0x13, 0x48, 0xb8, 0xbd, 0x7b, 0x35, - 0xc4, 0x00, 0x1e, 0x62, + 0x73, 0x7f, 0xae, 0x39, 0x10, 0xf9, 0x06, 0x3f, 0x60, 0x1e, 0x89, 0x02, 0x1b, 0x08, + 0xfa, 0x41, 0x40, 0x49, 0x1a, 0xfc, 0x55, 0xf7, 0x48, 0x66, 0x0e, 0x40, 0x73, 0x73, + 0xe8, 0x22, 0xd2, 0xfb, ], - note_v: 15425828902564319772, + asset: [ + 0x09, 0x07, 0x54, 0x17, 0xfc, 0xc0, 0x06, 0x2e, 0x49, 0xf0, 0x08, 0xc5, 0x1a, 0xd4, + 0x22, 0x74, 0x39, 0xc1, 0xb4, 0x47, 0x6c, 0xcd, 0x8e, 0x97, 0x86, 0x2d, 0xab, 0x7b, + 0xe1, 0xe8, 0xd3, 0x99, + ], + note_v: 11605778395872469956, note_rho: [ - 0x73, 0x6c, 0x23, 0x35, 0x7c, 0x85, 0xf4, 0x57, 0x91, 0xe1, 0x70, 0x80, 0x29, 0xd9, - 0x82, 0x4d, 0x90, 0x70, 0x46, 0x07, 0xf3, 0x87, 0xa0, 0x3e, 0x49, 0xbf, 0x98, 0x36, - 0x57, 0x44, 0x31, 0x34, + 0x9a, 0x7c, 0x23, 0xa9, 0x96, 0x94, 0x1d, 0x88, 0x9e, 0x46, 0x22, 0xa9, 0xb9, 0xb1, + 0xd5, 0x9d, 0x5e, 0x31, 0x90, 0x94, 0x31, 0x8c, 0xd4, 0x05, 0xba, 0x27, 0xb7, 0xe2, + 0xc0, 0x84, 0x76, 0x2d, ], note_rseed: [ - 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, - 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, 0xa0, 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, - 0x85, 0x7f, 0x82, 0x84, + 0x31, 0x45, 0x3e, 0xc4, 0x54, 0x9a, 0x4d, 0x97, 0x72, 0x9d, 0x03, 0x34, 0x60, 0xfc, + 0xf8, 0x9d, 0x64, 0x94, 0xf2, 0xff, 0xd7, 0x89, 0xe9, 0x80, 0x82, 0xea, 0x5c, 0xe9, + 0x53, 0x4b, 0x3a, 0xcd, ], note_cmx: [ - 0xc8, 0x52, 0x8f, 0x72, 0x2c, 0xd3, 0xe4, 0x7d, 0xc9, 0x9e, 0x1e, 0x38, 0x80, 0x56, - 0x37, 0x08, 0x15, 0xa9, 0xd0, 0x37, 0x97, 0x3d, 0x85, 0xca, 0xc7, 0xea, 0x38, 0xb5, - 0xa7, 0x16, 0xfa, 0x3b, + 0x48, 0xda, 0xaa, 0xc9, 0x22, 0x2d, 0xe0, 0x05, 0x2d, 0x34, 0xd3, 0x21, 0xc5, 0x89, + 0x7f, 0x86, 0x18, 0xee, 0xfb, 0xd5, 0xd5, 0x69, 0x91, 0x84, 0x30, 0x54, 0x94, 0x5a, + 0x55, 0x9c, 0x39, 0x1c, ], note_nf: [ - 0xac, 0xc2, 0xed, 0x2c, 0x7e, 0x3b, 0x19, 0x7e, 0x5c, 0xdb, 0x4a, 0x57, 0x63, 0x57, - 0xd5, 0xf1, 0x35, 0x39, 0x16, 0x26, 0xc7, 0xa8, 0x25, 0xd1, 0x0a, 0xa2, 0x60, 0xae, - 0x0b, 0x95, 0x81, 0x28, + 0x3a, 0xe6, 0x3f, 0xcb, 0x97, 0xb0, 0x79, 0xfd, 0x66, 0xd9, 0x72, 0x80, 0xec, 0xbc, + 0x9f, 0xd2, 0x84, 0xfb, 0x09, 0x35, 0x99, 0x36, 0x90, 0x24, 0x1c, 0xd9, 0x26, 0x41, + 0x66, 0xe3, 0x03, 0x07, ], }, TestVector { sk: [ - 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, 0x0d, 0xc0, - 0xb7, 0x16, 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, - 0x8f, 0x4e, 0x68, 0xf5, + 0xc0, 0x5e, 0xf2, 0x7c, 0x6e, 0x22, 0xee, 0x27, 0x3e, 0x15, 0x78, 0x6e, 0x39, 0x4c, + 0x8f, 0x1b, 0xe3, 0x16, 0x82, 0xa3, 0x01, 0x47, 0x96, 0x3a, 0xc8, 0xda, 0x8d, 0x41, + 0xd8, 0x04, 0x25, 0x84, ], ask: [ - 0x2d, 0x6e, 0x97, 0x3e, 0x17, 0x54, 0xd4, 0x17, 0x87, 0x93, 0x4c, 0x34, 0x55, 0x8c, - 0xfe, 0x99, 0x38, 0x44, 0x19, 0x99, 0x72, 0xd9, 0xa6, 0x34, 0x8b, 0x7a, 0x3d, 0xad, - 0xfc, 0xb6, 0x77, 0x2a, + 0xed, 0x13, 0xf6, 0x49, 0x3a, 0x75, 0x3e, 0x17, 0xed, 0xc2, 0xbe, 0x5e, 0xdc, 0xfb, + 0xf5, 0x84, 0x33, 0x50, 0x0d, 0x44, 0x39, 0xf0, 0xf7, 0x9e, 0xee, 0xa3, 0xfc, 0xc5, + 0x15, 0x8a, 0x94, 0x0f, ], ak: [ - 0x76, 0x21, 0x59, 0xa4, 0x14, 0xf5, 0x74, 0xb5, 0x39, 0x75, 0x0f, 0x22, 0xc8, 0x86, - 0x3b, 0x02, 0xd2, 0x5c, 0xc1, 0x0c, 0x90, 0x71, 0xfc, 0x02, 0x19, 0xe9, 0x7f, 0x93, - 0x92, 0xd0, 0x67, 0x0c, + 0xfb, 0x04, 0x81, 0x83, 0xeb, 0x36, 0xaa, 0x92, 0xe0, 0x12, 0x52, 0xd7, 0xf7, 0x7d, + 0x5f, 0xf6, 0x6b, 0xed, 0xf7, 0xe2, 0x70, 0x2e, 0xf7, 0x96, 0x72, 0x8f, 0x7e, 0x2a, + 0x5f, 0xb3, 0x14, 0x18, + ], + isk: [ + 0xd7, 0xc1, 0x11, 0xa6, 0x8e, 0xf4, 0x4b, 0xcd, 0x0c, 0x15, 0x13, 0xad, 0x47, 0xca, + 0x61, 0xc6, 0x59, 0xcc, 0x5d, 0x32, 0x5b, 0x44, 0x0f, 0x6b, 0x9f, 0x59, 0xaf, 0xf6, + 0x68, 0x79, 0xbb, 0x66, + ], + ik: [ + 0x0c, 0x40, 0xa2, 0x9b, 0xdb, 0xe3, 0xe4, 0x5d, 0x2c, 0xb7, 0xc1, 0x41, 0xed, 0xe0, + 0xce, 0x2c, 0xe9, 0x2c, 0xa6, 0xbf, 0x9f, 0x6b, 0xc0, 0x42, 0xb0, 0xe7, 0x25, 0x24, + 0xf4, 0x19, 0x5c, 0xa6, ], nk: [ - 0x25, 0x91, 0xed, 0xf7, 0xef, 0x4c, 0xf2, 0x18, 0x4c, 0x34, 0xbe, 0x93, 0xfc, 0xf6, - 0x12, 0x91, 0x50, 0x42, 0xf1, 0x5a, 0xb5, 0x08, 0x4b, 0x14, 0xe1, 0x66, 0x79, 0x5b, - 0x09, 0xce, 0xa1, 0x33, + 0x2c, 0x5c, 0xc2, 0x37, 0x14, 0xa6, 0x22, 0xa0, 0xb9, 0xe2, 0x0a, 0x1f, 0x0f, 0x23, + 0x07, 0x26, 0x90, 0xd3, 0x4e, 0x1e, 0xd2, 0x75, 0xfd, 0x22, 0x9b, 0xca, 0x65, 0x46, + 0x96, 0x5c, 0xf6, 0x3d, ], rivk: [ - 0x75, 0x8f, 0xb2, 0x50, 0xdd, 0x29, 0x50, 0xe5, 0xd2, 0xb2, 0xee, 0xd7, 0xff, 0xcf, - 0x94, 0xae, 0x67, 0xcd, 0xe1, 0x25, 0xb9, 0x5b, 0x47, 0x9e, 0x23, 0x77, 0x81, 0x3a, - 0x85, 0xa0, 0x3d, 0x2f, + 0x7e, 0x13, 0x20, 0x87, 0x56, 0x5e, 0xe9, 0xc5, 0x5b, 0x6d, 0x6f, 0xea, 0x16, 0xba, + 0xee, 0xdc, 0xfb, 0x61, 0xa6, 0xed, 0xc3, 0xce, 0xc3, 0xb0, 0x5a, 0x96, 0x0d, 0x20, + 0x1d, 0xd1, 0xa4, 0x2a, ], ivk: [ - 0x6e, 0xa4, 0x36, 0x3c, 0xb2, 0xdf, 0x62, 0xb1, 0x0d, 0xa1, 0x30, 0x8a, 0x0b, 0x96, - 0x79, 0xbd, 0x0f, 0x74, 0x95, 0xff, 0xe7, 0xd4, 0xe2, 0x61, 0x8f, 0x54, 0xdf, 0x9b, - 0x67, 0x0c, 0x33, 0x16, + 0x4d, 0x73, 0x82, 0x9c, 0x52, 0x03, 0x47, 0x9f, 0x58, 0x44, 0xf8, 0xa5, 0x8f, 0x3c, + 0xef, 0xa9, 0xde, 0x8e, 0xaa, 0x95, 0xfa, 0x84, 0x22, 0x7b, 0xf7, 0xa8, 0xed, 0x69, + 0x08, 0xb3, 0xb7, 0x35, ], ovk: [ - 0xa6, 0x3c, 0xbc, 0xd3, 0x1b, 0xa1, 0x36, 0xd8, 0x3b, 0x8f, 0x1e, 0x88, 0xef, 0xb6, - 0x00, 0x55, 0xef, 0x6f, 0x98, 0x25, 0x2d, 0xdb, 0xd7, 0x5f, 0x62, 0x5f, 0x44, 0xdc, - 0xb6, 0x63, 0x2c, 0x72, + 0xde, 0xf9, 0x9b, 0x97, 0x9d, 0xb5, 0x59, 0x7b, 0x55, 0x72, 0xa8, 0x43, 0x5b, 0x6d, + 0x00, 0xab, 0xe1, 0xbb, 0x84, 0x74, 0x67, 0xf3, 0x3c, 0xcb, 0x0b, 0x9d, 0x0c, 0xa3, + 0xdd, 0x11, 0xee, 0xa6, ], dk: [ - 0x02, 0xf0, 0x74, 0x08, 0xf3, 0x3e, 0x87, 0x12, 0xe4, 0xc9, 0xec, 0x42, 0xde, 0x56, - 0x04, 0x20, 0x01, 0x09, 0x86, 0x17, 0x24, 0xd3, 0x3e, 0xb6, 0x36, 0x8b, 0x70, 0xf6, - 0x5e, 0x0a, 0x16, 0x21, + 0xb0, 0x84, 0xe4, 0x86, 0x25, 0x45, 0x43, 0x7e, 0x11, 0x7e, 0x7a, 0x7b, 0xa9, 0x67, + 0xa3, 0xfd, 0xa7, 0x2e, 0x9b, 0x0a, 0x1d, 0x82, 0x9a, 0xaa, 0x6d, 0x63, 0x8b, 0xb5, + 0x22, 0x1a, 0xe9, 0x41, ], default_d: [ - 0x08, 0xdf, 0x1d, 0x4b, 0x45, 0xc6, 0x73, 0xa4, 0x59, 0xff, 0x58, + 0xda, 0x61, 0x78, 0xe2, 0x65, 0xc7, 0xbc, 0xe8, 0x7d, 0x3e, 0xca, ], default_pk_d: [ - 0x26, 0x8c, 0xc2, 0x4b, 0x38, 0xa6, 0x28, 0x80, 0xb6, 0xee, 0x3c, 0xbc, 0xb8, 0x5a, - 0x71, 0x2f, 0xa6, 0x86, 0xcf, 0xfc, 0xa6, 0xdb, 0x2f, 0xee, 0xc5, 0xf3, 0xc3, 0x56, - 0x6f, 0x84, 0x21, 0x8f, + 0x14, 0xba, 0x11, 0x2b, 0x9e, 0xb9, 0xa8, 0xb8, 0x48, 0x55, 0x52, 0xbf, 0xf6, 0x77, + 0x36, 0x4c, 0x8b, 0x8d, 0x37, 0x2c, 0xc2, 0x98, 0x96, 0x00, 0xe9, 0x8a, 0x53, 0xa6, + 0xbe, 0xd1, 0xdc, 0x3a, ], internal_rivk: [ - 0x00, 0x57, 0x37, 0x74, 0x61, 0xf2, 0x19, 0x1a, 0x7e, 0xca, 0x2b, 0x02, 0xed, 0xfd, - 0x9c, 0x9b, 0x44, 0x84, 0x5d, 0x2f, 0xdb, 0x8a, 0x99, 0xc7, 0x61, 0x20, 0x52, 0x7e, - 0x53, 0xdd, 0x09, 0x17, + 0xab, 0x1b, 0x90, 0x4f, 0xb6, 0x34, 0x09, 0x39, 0x84, 0xbf, 0x42, 0x9f, 0xeb, 0x53, + 0x3f, 0x22, 0x5d, 0xa0, 0xad, 0x22, 0xb8, 0x85, 0x64, 0x4f, 0x0b, 0xec, 0x49, 0x2e, + 0xc6, 0x3f, 0x48, 0x18, ], internal_ivk: [ - 0x81, 0x62, 0x97, 0x35, 0x09, 0x47, 0x0c, 0x44, 0x24, 0x19, 0x11, 0xc0, 0x6d, 0x04, - 0x02, 0x9f, 0x5f, 0x1f, 0x0e, 0x98, 0x51, 0xe3, 0x2b, 0xa6, 0x9b, 0x18, 0xe5, 0x81, - 0x05, 0xdd, 0x4e, 0x2b, + 0x70, 0xf2, 0x2d, 0x49, 0x0e, 0x62, 0xb3, 0x3e, 0x39, 0xa9, 0xfe, 0x06, 0x50, 0xa6, + 0x0e, 0x09, 0x13, 0x1d, 0x77, 0xd9, 0xb9, 0x4a, 0x61, 0x52, 0xc1, 0x63, 0x9d, 0xa6, + 0xe7, 0xaa, 0x01, 0x1c, ], internal_ovk: [ - 0x69, 0x47, 0x91, 0x0e, 0xa3, 0xe7, 0x33, 0x1d, 0x15, 0xa7, 0x1a, 0x64, 0xb2, 0xa8, - 0xc1, 0x6a, 0x6d, 0xa0, 0x8e, 0x6f, 0x34, 0x29, 0xdb, 0x26, 0xf9, 0x37, 0xab, 0x9d, - 0xd1, 0x33, 0xb5, 0xfd, + 0x73, 0xa9, 0x08, 0x2e, 0x80, 0xd8, 0x5e, 0x44, 0x58, 0x54, 0xef, 0xb4, 0xdf, 0x15, + 0x89, 0xcf, 0xbf, 0x72, 0x5b, 0xe3, 0xf7, 0xa7, 0x77, 0xb6, 0xa5, 0x1a, 0x35, 0xea, + 0x5d, 0x74, 0xc3, 0xd9, ], internal_dk: [ - 0x32, 0x7f, 0x76, 0xcc, 0x42, 0x44, 0xce, 0x0a, 0x91, 0x48, 0xa3, 0x5a, 0x7e, 0xa6, - 0x22, 0x8d, 0x44, 0x1c, 0x4c, 0x7b, 0x05, 0xbd, 0x02, 0x65, 0x7c, 0xea, 0xab, 0xb6, - 0x09, 0xbc, 0x3c, 0x52, + 0x3f, 0x4b, 0xa3, 0xf2, 0x3c, 0x10, 0x3e, 0x92, 0x3e, 0x39, 0x26, 0xd0, 0x9d, 0xc0, + 0x10, 0xab, 0x08, 0xb3, 0x9c, 0x90, 0x8a, 0x61, 0x89, 0x7f, 0xa1, 0x27, 0x27, 0xa2, + 0x0b, 0xd6, 0x27, 0xbd, ], - note_v: 12606128263924155660, + asset: [ + 0x88, 0xfd, 0x28, 0x59, 0x36, 0x2b, 0x18, 0x2f, 0x20, 0x7b, 0x31, 0x75, 0x96, 0x1f, + 0x64, 0x11, 0xa4, 0x93, 0xbf, 0xfd, 0x04, 0x8e, 0x7d, 0x0d, 0x87, 0xd8, 0x2f, 0xe6, + 0xf9, 0x90, 0xa2, 0xb0, + ], + note_v: 1850337920518955814, note_rho: [ - 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, - 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, - 0x43, 0x6a, 0x10, 0x2f, + 0x1e, 0x11, 0xbc, 0x33, 0xab, 0x75, 0xdd, 0x6c, 0xa0, 0x67, 0xfb, 0x73, 0xa0, 0x43, + 0xb6, 0x46, 0xa7, 0xcf, 0x39, 0xca, 0xb4, 0x92, 0x83, 0x86, 0x78, 0x6d, 0x2f, 0x24, + 0x14, 0x1e, 0xe1, 0x20, ], note_rseed: [ - 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, - 0x0d, 0x02, 0xe0, 0xf0, 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, - 0x29, 0x6e, 0xfa, 0xa7, + 0xfd, 0xc3, 0x4d, 0x67, 0x64, 0xea, 0xfc, 0x66, 0x88, 0x0e, 0xe0, 0x20, 0x4f, 0x53, + 0xcc, 0x11, 0x67, 0xed, 0x20, 0xb4, 0x3a, 0x52, 0xde, 0xa3, 0xca, 0x7c, 0xff, 0x8e, + 0xf3, 0x5c, 0xd8, 0xe6, ], note_cmx: [ - 0x6a, 0x11, 0x95, 0xaa, 0x05, 0x36, 0xf6, 0x0e, 0xcf, 0xae, 0xcb, 0xdf, 0x53, 0x74, - 0xe4, 0x94, 0xea, 0x07, 0x2a, 0x2b, 0x86, 0x7b, 0x5f, 0x69, 0x43, 0x40, 0xc9, 0x6f, - 0xc3, 0x70, 0xa9, 0x10, + 0x2d, 0x50, 0xf6, 0x82, 0x85, 0x0c, 0x72, 0x2b, 0x5f, 0x26, 0x15, 0x7e, 0x9c, 0xe8, + 0x4d, 0x12, 0x63, 0x3c, 0xc1, 0x93, 0x02, 0x5e, 0x13, 0x0c, 0x0f, 0xf5, 0xf0, 0xde, + 0xf6, 0x8d, 0x84, 0x21, ], note_nf: [ - 0xb0, 0xf1, 0x60, 0x2a, 0x2b, 0x1a, 0xf2, 0xfc, 0x55, 0xf1, 0x59, 0x50, 0xa6, 0x83, - 0x83, 0x85, 0xe5, 0xe3, 0x9f, 0xec, 0xfd, 0x05, 0xcc, 0xec, 0x79, 0x9b, 0x75, 0xc6, - 0x5c, 0x8d, 0xa2, 0x35, + 0xc7, 0x87, 0x80, 0x17, 0xd9, 0x2f, 0x36, 0xe3, 0xae, 0x78, 0x60, 0xeb, 0x0a, 0x8c, + 0x32, 0x3b, 0xa7, 0x4b, 0x23, 0xa7, 0x04, 0x48, 0x97, 0x84, 0x11, 0x77, 0xa6, 0x4d, + 0x50, 0x8a, 0x67, 0x20, ], }, TestVector { sk: [ - 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, - 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, - 0x84, 0x1e, 0x75, 0x17, + 0xa2, 0x5f, 0x5a, 0xa0, 0x11, 0x1a, 0x6e, 0x68, 0xf3, 0x7b, 0xf6, 0xf3, 0xac, 0x2d, + 0x26, 0xb8, 0x46, 0x86, 0xe5, 0x69, 0xd5, 0x8d, 0x99, 0xc1, 0x38, 0x35, 0x97, 0xfa, + 0xd8, 0x11, 0x93, 0xc4, ], ask: [ - 0x28, 0xdc, 0x45, 0xf1, 0x15, 0x44, 0x42, 0x5c, 0x1b, 0xef, 0x86, 0x61, 0xda, 0x11, - 0x15, 0x5f, 0xdb, 0xb7, 0xe3, 0xbc, 0xfc, 0x0f, 0x0d, 0x49, 0xe6, 0xf1, 0x31, 0xe7, - 0xc0, 0x9d, 0x35, 0x2f, + 0x91, 0xcb, 0x55, 0x3a, 0x4b, 0xfd, 0x80, 0xa0, 0x65, 0xbc, 0x32, 0xca, 0x6f, 0x8a, + 0x5d, 0xe1, 0xd7, 0x15, 0x99, 0xdb, 0x52, 0x7d, 0xb7, 0x04, 0x30, 0xee, 0x81, 0xc2, + 0x1e, 0x29, 0x05, 0x1a, ], ak: [ - 0x0d, 0x21, 0x1a, 0x90, 0x60, 0xfb, 0xaa, 0x66, 0x4e, 0x41, 0xa7, 0x34, 0xad, 0x1d, - 0x8d, 0x4b, 0x02, 0x5f, 0x8c, 0xc1, 0x60, 0xe1, 0xf4, 0xe9, 0x5f, 0x0a, 0x85, 0x3e, - 0xbc, 0x41, 0x6a, 0x2b, + 0xf6, 0x5c, 0x7d, 0xf2, 0x87, 0x16, 0x69, 0xbd, 0x0d, 0x82, 0xaa, 0xfe, 0x1f, 0x89, + 0xfe, 0xfd, 0xaf, 0xd6, 0x28, 0x17, 0x65, 0x3c, 0x38, 0xc2, 0x4a, 0xda, 0xe0, 0xfc, + 0x62, 0xe0, 0xc0, 0x0f, + ], + isk: [ + 0x90, 0x3f, 0x5d, 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, + 0x4d, 0x63, 0x59, 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, + 0x6c, 0x4a, 0x2f, 0xbe, + ], + ik: [ + 0x6c, 0xc4, 0x46, 0x5c, 0x0a, 0x64, 0xa5, 0xec, 0x41, 0x96, 0x8a, 0x80, 0x9f, 0x71, + 0x3d, 0xf6, 0xf3, 0x45, 0x1c, 0x5e, 0xec, 0xff, 0xf5, 0x31, 0x7a, 0x21, 0x0c, 0xc7, + 0xc8, 0x50, 0xbd, 0x51, ], nk: [ - 0x3e, 0x88, 0xf2, 0x07, 0x1f, 0xd9, 0xa2, 0xbb, 0x26, 0xcd, 0xa2, 0xea, 0x85, 0x6a, - 0xa0, 0xfb, 0x3a, 0x80, 0xa8, 0x7d, 0x2f, 0xb6, 0x13, 0x6f, 0xab, 0x85, 0xe3, 0x6c, - 0x5b, 0x38, 0xd8, 0x24, + 0x5c, 0x39, 0x80, 0xe1, 0x5d, 0xba, 0xd3, 0x67, 0xf4, 0xa1, 0xd3, 0x89, 0x15, 0x78, + 0x30, 0x61, 0xe2, 0x87, 0x98, 0x17, 0x3f, 0x14, 0x7f, 0xaf, 0xb4, 0xcb, 0x2c, 0x6d, + 0x1f, 0x44, 0xc0, 0x06, ], rivk: [ - 0x2c, 0x37, 0x38, 0x82, 0xc4, 0x08, 0xcd, 0x5f, 0xd4, 0x82, 0xa0, 0xc9, 0x81, 0x6f, - 0xc3, 0x22, 0x03, 0xa1, 0x0f, 0xbf, 0xce, 0x0e, 0x20, 0x0c, 0xcf, 0xd9, 0xee, 0x30, - 0x7c, 0x5e, 0x12, 0x24, + 0x1c, 0x91, 0x40, 0xc9, 0x47, 0x8f, 0x3a, 0x2b, 0xaf, 0xa6, 0x69, 0x0a, 0xbc, 0x5d, + 0x9e, 0x0d, 0x5e, 0x06, 0x01, 0xb3, 0x89, 0x4d, 0xb8, 0x3a, 0xb9, 0x9e, 0xe7, 0xe8, + 0x66, 0x4e, 0xab, 0x13, ], ivk: [ - 0xbb, 0x9e, 0x20, 0xb2, 0x99, 0x1c, 0x99, 0x6d, 0xa2, 0x1e, 0x3e, 0xcd, 0x39, 0xfb, - 0x7b, 0x3a, 0xa2, 0xba, 0xbc, 0x6b, 0xde, 0x18, 0x6f, 0x7d, 0xd8, 0xa8, 0x75, 0xd1, - 0x0c, 0x51, 0xa4, 0x30, + 0xcd, 0xdb, 0xbc, 0xe7, 0xf9, 0x62, 0x50, 0x76, 0x5a, 0x84, 0x60, 0xbb, 0x7a, 0xf1, + 0xa6, 0x4f, 0x2b, 0x9e, 0x9e, 0x62, 0x37, 0x67, 0x28, 0x0e, 0x41, 0x0f, 0x80, 0x1a, + 0xa8, 0x67, 0x81, 0x38, ], ovk: [ - 0x93, 0x21, 0x83, 0x8a, 0x2d, 0xb7, 0xf1, 0x68, 0xf0, 0xce, 0x77, 0xc4, 0x5b, 0x21, - 0x1f, 0xfb, 0xb9, 0xb3, 0x65, 0xe8, 0x5e, 0x67, 0x31, 0xd9, 0x09, 0x70, 0x05, 0x53, - 0xde, 0x49, 0x2b, 0x28, + 0x6f, 0x31, 0x6e, 0x8e, 0x63, 0x21, 0x24, 0xdb, 0xf8, 0x99, 0x27, 0x54, 0x40, 0xea, + 0x2e, 0xb0, 0x5a, 0xb2, 0x07, 0xc1, 0x85, 0x06, 0x99, 0xf8, 0xe7, 0x9a, 0x3f, 0xa2, + 0x2d, 0x62, 0x9f, 0xc1, ], dk: [ - 0x3d, 0xf5, 0x83, 0x36, 0x1b, 0x33, 0x38, 0xbb, 0x68, 0x15, 0xf8, 0x58, 0x72, 0xe3, - 0x9f, 0x04, 0xdf, 0x50, 0x08, 0x52, 0x48, 0x84, 0xaf, 0x0f, 0x8c, 0x55, 0x97, 0x16, - 0xfc, 0xb1, 0x49, 0x58, + 0x48, 0x4d, 0xee, 0x22, 0x4f, 0xff, 0x5d, 0x93, 0xcf, 0x60, 0x47, 0x1c, 0xc3, 0x59, + 0xd0, 0x11, 0xb2, 0x25, 0x09, 0x34, 0x6d, 0x24, 0xc5, 0x24, 0x19, 0xae, 0x8e, 0x59, + 0x4f, 0x6b, 0x69, 0x51, ], default_d: [ - 0x4c, 0x40, 0x64, 0xc4, 0x7a, 0x5c, 0xa6, 0xe7, 0x5d, 0x46, 0x44, + 0xd9, 0xf7, 0x9c, 0xe9, 0xb0, 0xd6, 0x41, 0x19, 0x27, 0x1b, 0xe0, ], default_pk_d: [ - 0xf5, 0x17, 0x17, 0x4b, 0xe2, 0x58, 0x92, 0x32, 0x78, 0xcf, 0x45, 0x89, 0x08, 0xc0, - 0x73, 0x56, 0x49, 0xf1, 0x89, 0x9d, 0xb9, 0x9c, 0x3b, 0xa9, 0x00, 0x3f, 0x4b, 0xa3, - 0x0a, 0xb0, 0xd2, 0x10, + 0x98, 0x58, 0xd5, 0x94, 0x2c, 0x7d, 0xea, 0xef, 0xf9, 0xc5, 0x41, 0xd5, 0x0f, 0x18, + 0x10, 0x66, 0xc5, 0x57, 0xe6, 0xc7, 0xdc, 0xf0, 0x5b, 0x31, 0x25, 0xc7, 0xcd, 0x3a, + 0x67, 0x67, 0x3e, 0xbd, ], internal_rivk: [ - 0xd8, 0x09, 0xa2, 0xa3, 0xd3, 0x6e, 0xf9, 0x6d, 0xc5, 0x63, 0xf8, 0xa7, 0xb4, 0x13, - 0x90, 0x8b, 0xfd, 0xff, 0xc0, 0x6d, 0x51, 0x06, 0x48, 0x49, 0xef, 0x88, 0x6b, 0x6a, - 0x1d, 0x1d, 0x7c, 0x3f, + 0xe6, 0xff, 0x0f, 0xd9, 0xbf, 0xb9, 0xf8, 0x44, 0x9c, 0xa3, 0xf2, 0x76, 0x9b, 0x9d, + 0x32, 0x46, 0xd9, 0x6b, 0xd8, 0x1b, 0x57, 0xa4, 0xef, 0xaf, 0x78, 0xce, 0x77, 0xee, + 0xd5, 0x8d, 0x9c, 0x31, ], internal_ivk: [ - 0xae, 0x18, 0xa9, 0xa4, 0x25, 0x12, 0x38, 0x7f, 0x92, 0xee, 0xc1, 0x34, 0xbd, 0xe5, - 0x28, 0xb6, 0x2b, 0x61, 0xe9, 0x95, 0x6f, 0x9f, 0xb3, 0xc7, 0xd6, 0x5e, 0x19, 0x45, - 0xda, 0x34, 0xf3, 0x09, + 0xd6, 0x50, 0xa5, 0x8d, 0xcb, 0x1f, 0x01, 0x53, 0x7e, 0x64, 0x81, 0xa1, 0x9b, 0xc6, + 0x84, 0x65, 0xa2, 0xd3, 0x70, 0x13, 0xb2, 0xc3, 0xd6, 0x33, 0x77, 0x19, 0xd1, 0x8c, + 0xc0, 0xa7, 0x87, 0x38, ], internal_ovk: [ - 0x67, 0xa6, 0xd8, 0x4a, 0x81, 0x66, 0x32, 0x6c, 0xf3, 0x4c, 0xed, 0xff, 0xd4, 0x29, - 0x8a, 0x13, 0xb8, 0x01, 0xcb, 0x12, 0x2d, 0x5f, 0x33, 0x29, 0xa1, 0x59, 0x9f, 0x31, - 0xea, 0xdf, 0x5b, 0x17, + 0x0f, 0x03, 0xa8, 0xda, 0x4c, 0x6a, 0x0a, 0x3a, 0xe6, 0xd2, 0x18, 0xf0, 0x36, 0xce, + 0x95, 0x33, 0x24, 0x13, 0xe3, 0x4e, 0x31, 0x92, 0xfd, 0xe2, 0x99, 0x03, 0x34, 0x63, + 0x21, 0x15, 0xd7, 0x8b, ], internal_dk: [ - 0xa0, 0x07, 0x3a, 0xdd, 0xfb, 0x89, 0xc9, 0xcc, 0x34, 0x9e, 0xad, 0x5a, 0x92, 0xb7, - 0xd4, 0x17, 0xfe, 0x0e, 0x61, 0xf4, 0xa7, 0xe5, 0x66, 0x69, 0xc9, 0x07, 0xd4, 0x17, - 0x46, 0xc0, 0x72, 0xb9, + 0x06, 0x14, 0x5a, 0x2e, 0xe8, 0xbb, 0xe0, 0x91, 0x31, 0xce, 0x4b, 0xfe, 0x10, 0x53, + 0x23, 0x9c, 0x1b, 0xbf, 0xb3, 0xec, 0xb1, 0x4f, 0x73, 0xa8, 0x4b, 0x8f, 0x11, 0xf2, + 0x39, 0x4f, 0xac, 0xc9, + ], + asset: [ + 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, 0x90, + 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, 0x46, + 0x06, 0xc9, 0xcf, 0x9f, ], - note_v: 625536973899669523, + note_v: 564606438193672641, note_rho: [ - 0x03, 0xfd, 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, - 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, - 0x64, 0x0a, 0x69, 0x30, + 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, 0xbc, 0x00, 0x0a, + 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, 0x66, 0x94, 0x13, + 0xf8, 0x38, 0x79, 0x33, ], note_rseed: [ - 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, 0x16, 0x71, - 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, - 0xa1, 0x55, 0xfa, 0x3a, + 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, + 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, + 0xaf, 0x71, 0xb8, 0x9f, ], note_cmx: [ - 0xf7, 0x0e, 0xbf, 0x0f, 0x5e, 0xe5, 0xda, 0x6c, 0x6c, 0xde, 0xff, 0x8f, 0xec, 0x2f, - 0x8e, 0xed, 0x65, 0xc8, 0x8e, 0x67, 0x55, 0xda, 0xf1, 0x14, 0xd5, 0x54, 0xaf, 0x19, - 0x67, 0xa7, 0xf4, 0x0a, + 0x6c, 0x90, 0x39, 0xd8, 0xb1, 0x63, 0x00, 0x14, 0x9e, 0xe7, 0x27, 0x3e, 0x5e, 0xef, + 0x5e, 0xdb, 0x90, 0x87, 0xd8, 0x6c, 0x11, 0xfa, 0xf7, 0xab, 0xaf, 0xcd, 0x21, 0xad, + 0x0a, 0x76, 0xf8, 0x11, ], note_nf: [ - 0x95, 0x64, 0x97, 0x28, 0x46, 0x5e, 0x68, 0x2a, 0xc0, 0x57, 0xad, 0x87, 0x62, 0x94, - 0xd7, 0x00, 0xc2, 0x7f, 0xeb, 0xa2, 0xf7, 0x50, 0x92, 0x2f, 0x95, 0x51, 0x85, 0x70, - 0x62, 0x61, 0xc3, 0x0c, + 0x20, 0xc9, 0x4a, 0x43, 0xa7, 0xcf, 0xdc, 0x63, 0xd7, 0x07, 0x01, 0xf5, 0xad, 0xcc, + 0x79, 0x5a, 0x31, 0x08, 0x7d, 0x5e, 0xc3, 0x9a, 0x73, 0x6f, 0x81, 0xd8, 0x6e, 0x84, + 0x9a, 0xb2, 0xd6, 0x3b, ], }, ] diff --git a/src/test_vectors/merkle_path.rs b/src/test_vectors/merkle_path.rs index ff0270d2d..930d7721d 100644 --- a/src/test_vectors/merkle_path.rs +++ b/src/test_vectors/merkle_path.rs @@ -1,3 +1,5 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_merkle_tree) + pub(crate) struct TestVector { pub(crate) leaves: [[u8; 32]; 16], pub(crate) paths: [[[u8; 32]; 4]; 16], @@ -5,7 +7,6 @@ pub(crate) struct TestVector { } pub(crate) fn test_vectors() -> Vec { - // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_merkle_tree.py vec![ TestVector { leaves: [ diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption_vanilla.rs similarity index 60% rename from src/test_vectors/note_encryption.rs rename to src/test_vectors/note_encryption_vanilla.rs index e27ec24d8..72e88042c 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption_vanilla.rs @@ -97,34 +97,34 @@ pub(crate) fn test_vectors() -> Vec { 0xc1, 0x3e, 0x71, 0x01, ], nf_old: [ - 0xc5, 0x96, 0xfb, 0xd3, 0x2e, 0xbb, 0xcb, 0xad, 0xae, 0x60, 0xd2, 0x85, 0xc7, 0xd7, - 0x5f, 0xa8, 0x36, 0xf9, 0xd2, 0xfa, 0x86, 0x10, 0x0a, 0xb8, 0x58, 0xea, 0x2d, 0xe1, - 0xf1, 0x1c, 0x83, 0x06, + 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, + 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, + 0x05, 0xee, 0xf3, 0x27, ], cmx: [ - 0xa5, 0x70, 0x6f, 0x3d, 0x1b, 0x68, 0x8e, 0x9d, 0xc6, 0x34, 0xee, 0xe4, 0xe6, 0x5b, - 0x02, 0x8a, 0x43, 0xee, 0xae, 0xd2, 0x43, 0x5b, 0xea, 0x2a, 0xe3, 0xd5, 0x16, 0x05, - 0x75, 0xc1, 0x1a, 0x3b, + 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, + 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, + 0xf1, 0x7b, 0xd9, 0x21, ], esk: [ - 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, 0xd3, 0x5a, 0xd7, 0x46, - 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, 0x20, 0xa6, 0x25, 0xff, - 0x38, 0x77, 0xea, 0x3f, + 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, + 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, + 0xff, 0xf1, 0xbd, 0x1a, ], ephemeral_key: [ - 0xad, 0xdb, 0x47, 0xb6, 0xac, 0x5d, 0xfc, 0x16, 0x55, 0x89, 0x23, 0xd3, 0xa8, 0xf3, - 0x76, 0x09, 0x5c, 0x69, 0x5c, 0x04, 0x7c, 0x4e, 0x32, 0x66, 0xae, 0x67, 0x69, 0x87, - 0xf7, 0xe3, 0x13, 0x81, + 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, + 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, + 0xf5, 0xec, 0x45, 0x17, ], shared_secret: [ - 0x30, 0x3c, 0x1c, 0x3f, 0x2b, 0xcb, 0xb9, 0xd8, 0x49, 0x70, 0x15, 0xa6, 0xdf, 0xca, - 0x95, 0x4e, 0xce, 0x0d, 0x3b, 0x6c, 0xf1, 0x0a, 0xb9, 0xf7, 0x19, 0xeb, 0x89, 0x19, - 0x9e, 0xdf, 0xe9, 0x89, + 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, + 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, + 0x21, 0x50, 0x48, 0xa5, ], k_enc: [ - 0xef, 0x9d, 0x62, 0x25, 0x68, 0x7c, 0x2c, 0x91, 0x7b, 0x5c, 0xad, 0xa1, 0x75, 0x23, - 0xe8, 0xfb, 0xdb, 0x08, 0x82, 0x25, 0xaf, 0x2d, 0xb5, 0x72, 0xbb, 0x40, 0x0e, 0x44, - 0x8b, 0x5e, 0xa8, 0x71, + 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, + 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, + 0x79, 0x18, 0x03, 0x20, ], p_enc: [ 0x02, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, @@ -170,68 +170,68 @@ pub(crate) fn test_vectors() -> Vec { 0xee, 0xcc, 0x40, 0xa9, ], c_enc: [ - 0x1a, 0x9a, 0xdb, 0x14, 0x24, 0x98, 0xe3, 0xdc, 0xc7, 0x6f, 0xed, 0x77, 0x86, 0x14, - 0xdd, 0x31, 0x6c, 0x02, 0xfb, 0xb8, 0xba, 0x92, 0x44, 0xae, 0x4c, 0x2e, 0x32, 0xa0, - 0x7d, 0xae, 0xec, 0xa4, 0x12, 0x26, 0xb9, 0x8b, 0xfe, 0x74, 0xf9, 0xfc, 0xb2, 0x28, - 0xcf, 0xc1, 0x00, 0xf3, 0x18, 0x0f, 0x57, 0x75, 0xec, 0xe3, 0x8b, 0xe7, 0xed, 0x45, - 0xd9, 0x40, 0x21, 0xf4, 0x40, 0x1b, 0x2a, 0x4d, 0x75, 0x82, 0xb4, 0x28, 0xd4, 0x9e, - 0xc7, 0xf5, 0xb5, 0xa4, 0x98, 0x97, 0x3e, 0x60, 0xe3, 0x8e, 0x74, 0xf5, 0xc3, 0xe5, - 0x77, 0x82, 0x7c, 0x38, 0x28, 0x57, 0xd8, 0x16, 0x6b, 0x54, 0xe6, 0x4f, 0x66, 0xef, - 0x5c, 0x7e, 0x8c, 0x9b, 0xaa, 0x2a, 0x3f, 0xa9, 0xe3, 0x7d, 0x08, 0x77, 0x17, 0xd5, - 0xe9, 0x6b, 0xc2, 0xf7, 0x3d, 0x03, 0x14, 0x50, 0xdc, 0x24, 0x32, 0xba, 0x49, 0xd8, - 0xb7, 0x4d, 0xb2, 0x13, 0x09, 0x9e, 0xa9, 0xba, 0x04, 0xeb, 0x63, 0xb6, 0x57, 0x4d, - 0x46, 0xc0, 0x3c, 0xe7, 0x90, 0x0d, 0x4a, 0xc4, 0xbb, 0x18, 0x8e, 0xe9, 0x03, 0x0d, - 0x7f, 0x69, 0xc8, 0x95, 0xa9, 0x4f, 0xc1, 0x82, 0xf2, 0x25, 0xa9, 0x4f, 0x0c, 0xde, - 0x1b, 0x49, 0x88, 0x68, 0x71, 0xa3, 0x76, 0x34, 0x1e, 0xa9, 0x41, 0x71, 0xbe, 0xfd, - 0x95, 0xa8, 0x30, 0xfa, 0x18, 0x40, 0x70, 0x97, 0xdc, 0xa5, 0x11, 0x02, 0x54, 0x63, - 0xd4, 0x37, 0xe9, 0x69, 0x5c, 0xaa, 0x07, 0x9a, 0x2f, 0x68, 0xcd, 0xc7, 0xf2, 0xc1, - 0x32, 0x67, 0xbf, 0xf4, 0x19, 0x51, 0x37, 0xfa, 0x89, 0x53, 0x25, 0x2a, 0x81, 0xb2, - 0xaf, 0xa1, 0x58, 0x2b, 0x9b, 0xfb, 0x4a, 0xc9, 0x60, 0x37, 0xed, 0x29, 0x91, 0xd3, - 0xcb, 0xc7, 0xd5, 0x4a, 0xff, 0x6e, 0x62, 0x1b, 0x06, 0xa7, 0xb2, 0xb9, 0xca, 0xf2, - 0x95, 0x5e, 0xfa, 0xf4, 0xea, 0x8e, 0xfc, 0xfd, 0x02, 0x3a, 0x3c, 0x17, 0x48, 0xdf, - 0x3c, 0xbd, 0x43, 0xe0, 0xb9, 0xa8, 0xb0, 0x94, 0x56, 0x88, 0xd5, 0x20, 0x56, 0xc1, - 0xd1, 0x6e, 0xea, 0x37, 0xe7, 0x98, 0xba, 0x31, 0xdc, 0x3e, 0x5d, 0x49, 0x52, 0xbd, - 0x51, 0xec, 0x76, 0x9d, 0x57, 0x88, 0xb6, 0xe3, 0x5f, 0xe9, 0x04, 0x2b, 0x95, 0xd4, - 0xd2, 0x17, 0x81, 0x40, 0x0e, 0xaf, 0xf5, 0x86, 0x16, 0xad, 0x56, 0x27, 0x96, 0x63, - 0x6a, 0x50, 0xb8, 0xed, 0x6c, 0x7f, 0x98, 0x1d, 0xc7, 0xba, 0x81, 0x4e, 0xff, 0x15, - 0x2c, 0xb2, 0x28, 0xa2, 0xea, 0xd2, 0xf8, 0x32, 0x66, 0x2f, 0xa4, 0xa4, 0xa5, 0x07, - 0x97, 0xb0, 0xf8, 0x5b, 0x62, 0xd0, 0x8b, 0x1d, 0xd2, 0xd8, 0xe4, 0x3b, 0x4a, 0x5b, - 0xfb, 0xb1, 0x59, 0xed, 0x57, 0x8e, 0xf7, 0x47, 0x5d, 0xe0, 0xad, 0xa1, 0x3e, 0x17, - 0xad, 0x87, 0xcc, 0x23, 0x05, 0x67, 0x2b, 0xcc, 0x55, 0xa8, 0x88, 0x13, 0x17, 0xfd, - 0xc1, 0xbf, 0xc4, 0x59, 0xb6, 0x8b, 0x2d, 0xf7, 0x0c, 0xad, 0x37, 0x70, 0xed, 0x0f, - 0xd0, 0x2d, 0x64, 0xb9, 0x6f, 0x2b, 0xbf, 0x6f, 0x8f, 0x63, 0x2e, 0x86, 0x6c, 0xa5, - 0xd1, 0x96, 0xd2, 0x48, 0xad, 0x05, 0xc3, 0xde, 0x64, 0x41, 0x48, 0xa8, 0x0b, 0x51, - 0xad, 0xa9, 0x5b, 0xd0, 0x8d, 0x73, 0xcd, 0xbb, 0x45, 0x26, 0x4f, 0x3b, 0xd1, 0x13, - 0x83, 0x5b, 0x46, 0xf9, 0xbe, 0x7b, 0x6d, 0x23, 0xa4, 0x3b, 0xdd, 0xfe, 0x1e, 0x74, - 0x08, 0xc9, 0x70, 0x31, 0xe1, 0xa8, 0x21, 0x4b, 0xab, 0x46, 0x39, 0x10, 0x44, 0xb7, - 0x00, 0xd3, 0x8f, 0x51, 0x92, 0xc5, 0x7f, 0xe6, 0xf8, 0x71, 0x59, 0xb5, 0x55, 0x12, - 0x09, 0x4e, 0x29, 0xd2, 0xce, 0xba, 0xb8, 0x68, 0xc8, 0xf1, 0xad, 0xba, 0xd5, 0x70, - 0x77, 0xcb, 0xeb, 0x5e, 0x69, 0x65, 0x85, 0x82, 0xbf, 0x98, 0xd1, 0x9d, 0x64, 0xf4, - 0x4b, 0x0d, 0x50, 0xc7, 0xe2, 0x20, 0x9a, 0xb3, 0xfc, 0x56, 0xb4, 0xf4, 0x09, 0x12, - 0x3a, 0xae, 0xb0, 0x26, 0x3a, 0x22, 0x45, 0x1b, 0xc1, 0x4e, 0xd7, 0x56, 0xd0, 0x48, - 0x38, 0x5a, 0xed, 0xbb, 0x86, 0xa8, 0x46, 0x77, 0xbb, 0x2d, 0x21, 0xc5, 0x2c, 0xc9, - 0x49, 0x41, 0x47, 0xbf, 0x0f, 0xb1, 0x02, 0x74, 0x52, 0x82, 0x99, 0x09, 0x09, 0x72, - 0x62, 0x28, 0x18, 0x6e, 0x02, 0xc8, + 0x93, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, + 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, + 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, + 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0x79, 0xfa, 0x88, 0x1a, + 0xbb, 0x48, 0xb7, 0x0d, 0xbc, 0x28, 0xdd, 0xf4, 0xaf, 0x81, 0xae, 0xed, 0x2a, 0x29, + 0x86, 0x00, 0x51, 0x08, 0x48, 0xed, 0xbd, 0xc4, 0x2e, 0x88, 0x95, 0x48, 0x70, 0xd5, + 0xd6, 0x01, 0xcd, 0xf2, 0x90, 0x18, 0x1b, 0x53, 0x91, 0x05, 0xb9, 0xf6, 0x13, 0x86, + 0xcb, 0x07, 0x84, 0x6b, 0xc8, 0xe3, 0x19, 0xdf, 0xab, 0x8e, 0x10, 0x97, 0x66, 0xa2, + 0x8c, 0x1e, 0x0b, 0xbf, 0x91, 0x32, 0x02, 0xce, 0xcd, 0x1b, 0x48, 0x17, 0xa2, 0x28, + 0x2f, 0xc2, 0x9e, 0xd4, 0x4d, 0x9b, 0x04, 0x04, 0x9d, 0xe5, 0x5a, 0xcf, 0x54, 0x99, + 0xe5, 0xf5, 0x65, 0xd4, 0x8b, 0x8f, 0x19, 0x72, 0xc0, 0x43, 0x84, 0x77, 0x96, 0x23, + 0x0d, 0xc6, 0x8f, 0x32, 0x57, 0xc0, 0x85, 0x29, 0x14, 0x8c, 0x8e, 0x0c, 0x32, 0x7b, + 0x25, 0xb4, 0x59, 0x87, 0x7c, 0xde, 0xd9, 0x8f, 0xf7, 0x8e, 0x81, 0xfa, 0x69, 0x2e, + 0x14, 0xf8, 0xfd, 0xa1, 0xfe, 0x52, 0x4f, 0xf1, 0x50, 0x18, 0x1f, 0x73, 0x6e, 0xd3, + 0xa8, 0x8e, 0xc7, 0x89, 0xdc, 0x15, 0x95, 0x4a, 0x02, 0x63, 0x9a, 0x8a, 0x20, 0xca, + 0x38, 0xd8, 0x99, 0xbf, 0xd1, 0xc5, 0x73, 0xb0, 0x41, 0xee, 0x7b, 0xf2, 0x2b, 0x96, + 0x75, 0xbd, 0xa8, 0xc4, 0xb0, 0x58, 0xa0, 0x5a, 0x49, 0x33, 0x03, 0xb1, 0x1f, 0x35, + 0x81, 0xc1, 0x9d, 0x2d, 0xa9, 0x96, 0x6a, 0x71, 0x06, 0x6e, 0xc1, 0x7d, 0xcc, 0xd3, + 0x48, 0x20, 0x7e, 0xb3, 0x14, 0xf6, 0xcf, 0xc9, 0xd0, 0x6a, 0x62, 0x14, 0xc6, 0x72, + 0x10, 0x97, 0xa5, 0x2e, 0x27, 0x76, 0x66, 0x7c, 0x6b, 0xe9, 0xc8, 0x86, 0x2b, 0x17, + 0x3d, 0xb0, 0xe8, 0x04, 0xb1, 0x2c, 0xaa, 0xe9, 0xd9, 0xfa, 0x09, 0xf3, 0xf4, 0x8c, + 0xaf, 0x4b, 0xf7, 0x56, 0xa2, 0x78, 0x95, 0x0a, 0x25, 0x4e, 0xc4, 0x14, 0x76, 0x77, + 0xaa, 0xca, 0x21, 0x42, 0x96, 0x08, 0x1a, 0x2f, 0x62, 0x4a, 0x92, 0x78, 0x94, 0x6e, + 0x68, 0x9d, 0xd9, 0x14, 0x02, 0x90, 0x92, 0xe7, 0xfa, 0x8f, 0xbc, 0x8a, 0x04, 0x46, + 0x7d, 0x60, 0xed, 0xff, 0x5d, 0x97, 0xcb, 0x65, 0x09, 0xa0, 0xc7, 0x2c, 0xed, 0x77, + 0xac, 0xa8, 0x71, 0x30, 0x8e, 0x7d, 0xe2, 0xbe, 0xb1, 0x52, 0x0a, 0x34, 0x17, 0xd7, + 0x21, 0x3a, 0x9a, 0xbd, 0x47, 0x35, 0x8c, 0x4f, 0x32, 0x9f, 0x0f, 0x64, 0x41, 0x92, + 0x10, 0xa9, 0x9d, 0xb2, 0xde, 0x6e, 0x6d, 0x89, 0x21, 0xb0, 0xf4, 0xf9, 0x9f, 0xd6, + 0x45, 0xfa, 0xe0, 0xd6, 0x29, 0xce, 0x22, 0x11, 0x90, 0x5f, 0x25, 0xf4, 0x0d, 0x12, + 0x0b, 0x63, 0x27, 0x93, 0x75, 0xb5, 0x43, 0xc3, 0x1e, 0x3b, 0x55, 0x7e, 0x57, 0xa7, + 0xa8, 0x7c, 0x61, 0x79, 0xeb, 0xd3, 0x4f, 0x6d, 0xbb, 0x92, 0x0e, 0xc5, 0xe0, 0x5d, + 0x6a, 0x77, 0xec, 0xdf, 0x36, 0xb4, 0x57, 0xba, 0xb4, 0x56, 0x6c, 0x40, 0x8f, 0xb5, + 0x7d, 0xfc, 0xdd, 0xda, 0xa4, 0x2c, 0x51, 0x34, 0xaf, 0x3e, 0x97, 0x8d, 0xbf, 0xd0, + 0xdf, 0xb0, 0xca, 0x4f, 0xfa, 0xf1, 0x65, 0x0a, 0xbe, 0xe1, 0x62, 0x5f, 0x7f, 0x4b, + 0xf8, 0x25, 0x06, 0x01, 0x00, 0x64, 0x5b, 0x54, 0xc0, 0x04, 0x1f, 0xbf, 0xbd, 0xef, + 0xf7, 0xb9, 0x38, 0x04, 0xe9, 0xcc, 0x0c, 0xcd, 0x6f, 0x27, 0xbe, 0x40, 0x01, 0x6c, + 0x32, 0xd4, 0x2f, 0xe3, 0x66, 0xfa, 0xaa, 0x86, 0x87, 0xc2, 0xd1, 0x92, 0x61, 0x9f, + 0x56, 0x5b, 0x0c, 0x70, 0xea, 0x6a, 0x3f, 0x79, 0xd5, 0x3a, 0x52, 0x41, 0xe6, 0x9c, + 0x3c, 0xa6, 0x87, 0xa1, 0x12, 0xfb, 0x16, 0xc2, 0x5c, 0xc0, 0x83, 0x17, 0xdb, 0xa4, + 0x23, 0x97, 0x0c, 0x32, 0xdf, 0xb4, 0xbd, 0x69, 0x22, 0xe3, 0x36, 0xab, 0xf2, 0xfd, + 0xe2, 0xc3, 0xaa, 0x5d, 0xb2, 0x93, 0xef, 0x27, 0x47, 0x87, 0x6c, 0x8b, 0xd8, 0x6e, + 0xa1, 0x87, 0xcb, 0x60, 0x1a, 0xf7, ], ock: [ - 0x4e, 0x9d, 0x45, 0x94, 0x6b, 0x3e, 0xea, 0xe7, 0xfe, 0x30, 0x5d, 0x5b, 0x90, 0x50, - 0x36, 0x14, 0x1f, 0x9f, 0x40, 0x09, 0xa6, 0x29, 0x4b, 0x96, 0xc7, 0x22, 0xa4, 0xa0, - 0xbe, 0x68, 0x5d, 0xff, + 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, + 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, + 0xc6, 0x6a, 0x1a, 0xd6, ], op: [ 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, - 0x49, 0x50, 0x69, 0x2c, 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, - 0xd3, 0x5a, 0xd7, 0x46, 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, - 0x20, 0xa6, 0x25, 0xff, 0x38, 0x77, 0xea, 0x3f, + 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, + 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, + 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, ], c_out: [ - 0xcb, 0xdf, 0x68, 0xa5, 0x7f, 0xb4, 0xa4, 0x6f, 0x34, 0x60, 0xff, 0x22, 0x7b, 0xc6, - 0x18, 0xda, 0xe1, 0x12, 0x29, 0x45, 0xb3, 0x80, 0xc7, 0xe5, 0x49, 0xcf, 0x4a, 0x6e, - 0x8b, 0xf3, 0x75, 0x49, 0xba, 0xe1, 0x89, 0x1f, 0xd8, 0xd1, 0xa4, 0x94, 0x4f, 0xdf, - 0x41, 0x0f, 0x07, 0x02, 0xed, 0xa5, 0x44, 0x2f, 0x0e, 0xa0, 0x1a, 0x5d, 0xf0, 0x12, - 0xa0, 0xae, 0x4d, 0x84, 0xed, 0x79, 0x80, 0x33, 0x28, 0xbd, 0x1f, 0xd5, 0xfa, 0xc7, - 0x19, 0x21, 0x6a, 0x77, 0x6d, 0xe6, 0x4f, 0xd1, 0x67, 0xdb, + 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, + 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, + 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, + 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, + 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, + 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, ], }, TestVector { @@ -306,34 +306,34 @@ pub(crate) fn test_vectors() -> Vec { 0x25, 0x7a, 0xd8, 0xb3, ], nf_old: [ - 0x33, 0x88, 0xda, 0x05, 0x06, 0xda, 0x9e, 0xa2, 0xd5, 0x16, 0x73, 0x9b, 0x95, 0x1c, - 0x7c, 0xc0, 0x58, 0x53, 0x36, 0xb4, 0x4d, 0xf9, 0xb3, 0xb5, 0x0e, 0x48, 0x93, 0xe4, - 0xb1, 0x84, 0x92, 0x11, + 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, + 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, + 0x4d, 0xb2, 0xc7, 0x31, ], cmx: [ - 0x9e, 0x04, 0x32, 0xb2, 0xb3, 0x33, 0xcd, 0xe8, 0xce, 0x92, 0x1b, 0x77, 0xca, 0x7e, - 0x9e, 0x41, 0x51, 0xe3, 0x74, 0xd5, 0x16, 0xcd, 0xa1, 0x17, 0x63, 0x83, 0x6a, 0xf3, - 0xb6, 0x6f, 0x5b, 0x15, + 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, + 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, + 0xc5, 0xe9, 0xf9, 0x0f, ], esk: [ - 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, 0x4d, 0x80, 0x4a, 0x17, - 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, 0x92, 0x1c, 0xd5, 0xda, - 0x8a, 0x6e, 0x1a, 0x08, + 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, + 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, + 0xbd, 0xc9, 0xce, 0x14, ], ephemeral_key: [ - 0x91, 0x92, 0x3e, 0xd8, 0x2b, 0x76, 0xd7, 0x97, 0x30, 0x7c, 0xaa, 0x23, 0x02, 0xc0, - 0xcf, 0x75, 0x56, 0x12, 0x17, 0x24, 0x98, 0x67, 0x53, 0x2a, 0xe5, 0x1c, 0x2e, 0xa0, - 0x05, 0xed, 0xad, 0xb6, + 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, + 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, + 0x31, 0x69, 0x85, 0x8c, ], shared_secret: [ - 0x53, 0xd7, 0xe4, 0x84, 0x3a, 0x36, 0xd5, 0x79, 0xb5, 0xa7, 0xc1, 0x04, 0x11, 0x96, - 0xbd, 0x4c, 0x85, 0x80, 0x5c, 0xcd, 0x0a, 0x3f, 0x95, 0xbc, 0x9e, 0x71, 0x06, 0x90, - 0xd1, 0x1b, 0x7a, 0xaa, + 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, + 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, + 0x68, 0x7e, 0xd9, 0xb0, ], k_enc: [ - 0xc2, 0xe3, 0x38, 0x9d, 0x6f, 0xc3, 0xcd, 0x06, 0x7f, 0x59, 0x0a, 0x93, 0x73, 0x05, - 0x04, 0xad, 0x9b, 0x63, 0xc4, 0x55, 0x45, 0x69, 0xb9, 0x62, 0x0f, 0x3e, 0xf0, 0xb0, - 0x65, 0x94, 0xde, 0xd6, + 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, + 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, + 0x58, 0x6a, 0xc0, 0xd9, ], p_enc: [ 0x02, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, @@ -379,68 +379,68 @@ pub(crate) fn test_vectors() -> Vec { 0x8b, 0x1e, 0x88, 0x6f, ], c_enc: [ - 0x6d, 0x21, 0x18, 0x0a, 0xc4, 0x74, 0x94, 0x57, 0x8a, 0x90, 0x06, 0xaf, 0x5b, 0xeb, - 0x4e, 0x34, 0x55, 0x59, 0xab, 0xdb, 0x0e, 0x23, 0xed, 0x52, 0x65, 0xaf, 0x79, 0xce, - 0x0c, 0xc5, 0x96, 0x71, 0xea, 0x31, 0x7b, 0x3e, 0xb1, 0x52, 0x93, 0xd1, 0xe0, 0x4a, - 0x9a, 0xd8, 0x39, 0x69, 0xab, 0x9e, 0x17, 0x08, 0xf2, 0x28, 0x85, 0x3a, 0x28, 0x1f, - 0xcf, 0x6c, 0x97, 0x60, 0xae, 0x71, 0x96, 0x5b, 0xb1, 0xd4, 0x45, 0x2e, 0x5e, 0xd0, - 0x06, 0x00, 0xab, 0x58, 0x94, 0x27, 0x75, 0xb7, 0x4e, 0x12, 0x62, 0xb4, 0x22, 0x5d, - 0x3b, 0x61, 0x9c, 0x31, 0x65, 0x96, 0xd7, 0xcf, 0x9c, 0x93, 0xbd, 0xb5, 0x2a, 0xfa, - 0x77, 0x8a, 0xa1, 0x20, 0x8d, 0x56, 0xd0, 0x69, 0xe5, 0x6e, 0x27, 0x79, 0x61, 0x4d, - 0x56, 0xf4, 0x36, 0x10, 0x72, 0xbc, 0x15, 0x16, 0xa9, 0xb4, 0x56, 0x2a, 0x4f, 0x54, - 0x63, 0xa5, 0x13, 0xc4, 0x59, 0x42, 0x15, 0x70, 0xf3, 0x34, 0xef, 0xb6, 0xbc, 0xd2, - 0x08, 0xf8, 0xf8, 0x05, 0x0e, 0x15, 0x3d, 0x4e, 0x61, 0xf3, 0x1e, 0xdd, 0xbb, 0x5a, - 0x98, 0xf1, 0x70, 0xd3, 0xd0, 0x80, 0xe8, 0xec, 0x3f, 0x65, 0x20, 0xb6, 0xa2, 0xd6, - 0x08, 0x83, 0xa5, 0x87, 0xff, 0x0e, 0x98, 0x21, 0x1c, 0x73, 0x45, 0x16, 0xb5, 0xdc, - 0xc7, 0x5e, 0xf2, 0x3c, 0xfb, 0x9f, 0x55, 0xf1, 0xde, 0xed, 0xf1, 0x26, 0xc2, 0xce, - 0x17, 0x27, 0x3f, 0x41, 0xdb, 0xbb, 0xbd, 0x2f, 0x49, 0xe3, 0x55, 0x77, 0x6e, 0xc0, - 0x46, 0x98, 0x35, 0xf7, 0x9d, 0x94, 0x80, 0x42, 0xf8, 0x42, 0x0f, 0x11, 0xe1, 0xab, - 0xd7, 0x45, 0x06, 0xb7, 0x8b, 0x5e, 0x41, 0xcb, 0xe0, 0xc7, 0x07, 0x17, 0xf4, 0x6e, - 0x7e, 0xb9, 0xac, 0xdc, 0x35, 0x1c, 0x94, 0x98, 0x83, 0x3a, 0xfd, 0xed, 0x93, 0x06, - 0xa0, 0x43, 0x5b, 0x10, 0xb8, 0x3a, 0xe3, 0x95, 0xd5, 0x7f, 0x5b, 0x0a, 0x5d, 0x41, - 0xa9, 0x34, 0x2d, 0x02, 0xec, 0x58, 0xb6, 0xee, 0x16, 0x87, 0x77, 0x50, 0x16, 0xb8, - 0x74, 0x9b, 0x28, 0x7a, 0xbd, 0xd3, 0xed, 0x1a, 0x83, 0x5e, 0xa8, 0xf3, 0xb1, 0x4d, - 0x08, 0x18, 0xfe, 0x0d, 0x5d, 0x9a, 0x48, 0xeb, 0x02, 0x13, 0x64, 0x0e, 0xec, 0xc1, - 0x9a, 0x5d, 0x16, 0x61, 0xdb, 0x82, 0x2b, 0x77, 0x9b, 0x08, 0x0c, 0xd8, 0xba, 0x7f, - 0x3a, 0x27, 0x23, 0x21, 0xee, 0x5d, 0xa2, 0x27, 0x8c, 0x53, 0x85, 0x67, 0xd0, 0xd9, - 0xbb, 0x28, 0xce, 0x64, 0x21, 0x31, 0x15, 0x03, 0xa4, 0xa0, 0x17, 0x14, 0xcf, 0x91, - 0x01, 0x55, 0x2b, 0xa5, 0xef, 0xc8, 0x5c, 0x94, 0xd5, 0xe5, 0x09, 0x72, 0x7e, 0x5e, - 0x01, 0x1c, 0x15, 0xb1, 0xb2, 0xec, 0xdf, 0xf3, 0x99, 0xc0, 0xbe, 0x33, 0x42, 0xab, - 0x6e, 0xdd, 0xa8, 0xe3, 0xed, 0x81, 0x1a, 0x7d, 0x9c, 0x9c, 0xa4, 0xbb, 0x71, 0xa5, - 0x63, 0xe1, 0x59, 0x78, 0xbf, 0x8e, 0x64, 0x04, 0xac, 0x79, 0x6e, 0xb7, 0x81, 0xfd, - 0x2c, 0xf2, 0x19, 0x1b, 0x2f, 0x4d, 0x40, 0x76, 0xd9, 0x3c, 0xcc, 0x80, 0xf7, 0xe5, - 0x92, 0xfa, 0x66, 0x9b, 0x72, 0x26, 0x57, 0x82, 0xee, 0x8f, 0x5c, 0xe3, 0x03, 0x12, - 0xd3, 0x51, 0x2b, 0x35, 0x49, 0x0a, 0xfe, 0x00, 0x6b, 0xad, 0xb1, 0x62, 0x0d, 0x1b, - 0x0c, 0x79, 0xfb, 0xc4, 0xbe, 0xc5, 0x65, 0xd7, 0x46, 0x1d, 0x68, 0xef, 0x72, 0x27, - 0x79, 0x11, 0x77, 0x6c, 0xd5, 0xa7, 0xb5, 0xfc, 0x6f, 0xa8, 0xb3, 0xee, 0xfd, 0x7a, - 0x39, 0xe8, 0xe5, 0xb4, 0xf6, 0xa5, 0x0c, 0x7d, 0x58, 0xd9, 0xeb, 0x08, 0x38, 0x0d, - 0x32, 0x0b, 0x36, 0xea, 0x04, 0x37, 0x00, 0xac, 0xa7, 0x64, 0xb4, 0x8c, 0x3d, 0xa4, - 0x93, 0x67, 0xfa, 0x93, 0x35, 0x6a, 0xaa, 0x4f, 0x87, 0x08, 0xea, 0x6e, 0x34, 0x59, - 0x81, 0x84, 0x5b, 0xe7, 0x37, 0x6d, 0xa7, 0x98, 0x40, 0x53, 0xef, 0x7d, 0xd4, 0xb6, - 0xa7, 0x27, 0x92, 0x35, 0x6a, 0x6c, 0x34, 0x62, 0x68, 0x88, 0xcc, 0x70, 0xde, 0x49, - 0x9e, 0xf9, 0x10, 0x26, 0x95, 0xd9, 0xdb, 0x12, 0xaf, 0x29, 0x62, 0xfc, 0x75, 0xd4, - 0x36, 0x56, 0x19, 0xdb, 0x0e, 0x87, 0x6c, 0xdb, 0x82, 0x02, 0xe8, 0x16, 0xfd, 0xc2, - 0xcd, 0xf3, 0x7a, 0xd3, 0xbe, 0x3b, + 0x1b, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, + 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, + 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, + 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0xba, 0x81, 0x0a, 0x99, + 0x8b, 0x82, 0x3a, 0x4a, 0xd2, 0x41, 0xaa, 0x9f, 0x4a, 0x3a, 0xe4, 0x82, 0x5d, 0xe9, + 0x95, 0xdd, 0x58, 0x73, 0x56, 0x62, 0x44, 0xbb, 0xd8, 0x75, 0xd0, 0x1b, 0xf3, 0x28, + 0xe8, 0x22, 0xca, 0xfd, 0xb8, 0x3e, 0xd7, 0x75, 0x3a, 0x88, 0x85, 0xd7, 0xae, 0xf2, + 0x45, 0x5a, 0x15, 0x2e, 0x23, 0xdf, 0xa2, 0xd6, 0x99, 0xb3, 0x5c, 0x33, 0xd3, 0x61, + 0x07, 0x2a, 0xe5, 0xc5, 0x12, 0x43, 0x4d, 0x34, 0x6f, 0x6c, 0x56, 0xfb, 0x5f, 0x11, + 0xb0, 0xb6, 0x47, 0xcb, 0xca, 0xfe, 0x02, 0xd8, 0x84, 0x55, 0xa6, 0x30, 0xa3, 0x50, + 0x86, 0x2b, 0x3c, 0xd1, 0x51, 0x3b, 0x6d, 0x6e, 0x41, 0x17, 0xc7, 0x5e, 0xc4, 0xb1, + 0x2f, 0xd7, 0x5a, 0x90, 0xf8, 0x2d, 0xce, 0xa1, 0xc7, 0x71, 0xfd, 0xda, 0x24, 0xec, + 0xf0, 0xa3, 0xe5, 0xb2, 0xe8, 0xa2, 0x24, 0x23, 0x6e, 0xf0, 0x9a, 0x93, 0xab, 0x59, + 0xe5, 0x9b, 0xdf, 0xb8, 0x72, 0x86, 0x0c, 0xc2, 0xd9, 0x11, 0x34, 0xca, 0xf2, 0x13, + 0x98, 0x48, 0xe3, 0x9a, 0xa6, 0x4b, 0xa2, 0xe6, 0xd7, 0x25, 0x20, 0x54, 0xf3, 0x7a, + 0xd5, 0x5c, 0x2c, 0xe5, 0xf8, 0x1b, 0x33, 0xcc, 0xb6, 0x8a, 0x94, 0x73, 0x71, 0x24, + 0x3a, 0x77, 0xe8, 0x43, 0x67, 0xd9, 0xd3, 0x5b, 0x11, 0x68, 0x14, 0x10, 0xea, 0x79, + 0x8b, 0x03, 0x87, 0xb8, 0xf1, 0x0b, 0x1f, 0x89, 0xc6, 0x8a, 0xd1, 0xcc, 0xa9, 0xa3, + 0xe0, 0x32, 0xf3, 0x49, 0x98, 0x79, 0xc8, 0x9a, 0xe6, 0x38, 0x2f, 0x38, 0x97, 0x22, + 0x01, 0x1f, 0x49, 0x25, 0x14, 0x3e, 0xa8, 0x50, 0x73, 0xe4, 0xff, 0x0c, 0xcf, 0x6d, + 0x77, 0x9b, 0xc3, 0xbf, 0x4c, 0x1b, 0x95, 0xfc, 0x7c, 0xf7, 0xf9, 0x91, 0xa2, 0x16, + 0x2a, 0xb9, 0x45, 0x41, 0xf3, 0x99, 0x8e, 0xf6, 0xbc, 0x3f, 0xe8, 0x02, 0x54, 0xab, + 0xa4, 0x1f, 0x15, 0x23, 0x15, 0x03, 0x45, 0x1b, 0x15, 0xe1, 0x08, 0x52, 0xf8, 0x5b, + 0xd2, 0xd1, 0x15, 0x93, 0x53, 0x14, 0xcd, 0x80, 0xc1, 0x23, 0xbe, 0x0b, 0x53, 0x0f, + 0xaa, 0xd6, 0xb5, 0x07, 0x49, 0x68, 0x22, 0x1d, 0xa0, 0x4b, 0x54, 0x6d, 0x96, 0x21, + 0x63, 0x29, 0x9d, 0x52, 0xce, 0xf4, 0x1e, 0x29, 0x6d, 0xa5, 0x9c, 0xb0, 0x76, 0xdb, + 0xe8, 0x99, 0x70, 0x4b, 0x61, 0x73, 0x0c, 0x19, 0xbd, 0x22, 0x1a, 0xd2, 0xbd, 0x29, + 0x81, 0xea, 0x95, 0x1b, 0xe0, 0x2c, 0x9f, 0x5b, 0xdf, 0x92, 0xd9, 0x87, 0x07, 0x46, + 0xb2, 0xa5, 0x8c, 0x3d, 0x18, 0xa7, 0xd3, 0xe5, 0xe2, 0xc6, 0x3a, 0xc2, 0x61, 0x58, + 0x37, 0xbe, 0x1c, 0x6f, 0xe0, 0x03, 0x65, 0x6c, 0x1b, 0x3d, 0x71, 0x50, 0x5f, 0x5e, + 0x21, 0x88, 0x10, 0x4e, 0x98, 0x91, 0x1b, 0x6a, 0x5e, 0x3f, 0x52, 0x82, 0xfa, 0xc0, + 0xc8, 0xfa, 0x1b, 0xa3, 0x6f, 0xfc, 0x07, 0xdc, 0x7a, 0x40, 0x9d, 0xf2, 0xeb, 0xa8, + 0xc7, 0x5f, 0x70, 0xbd, 0x59, 0xa6, 0xf0, 0x65, 0x1d, 0xc1, 0xb1, 0xb5, 0x96, 0xde, + 0x6a, 0xce, 0xc7, 0x78, 0xe2, 0xe3, 0x2f, 0x1e, 0xd4, 0x6d, 0xf7, 0xa9, 0xae, 0xf5, + 0x1d, 0xfe, 0x5a, 0xa5, 0x24, 0x36, 0xea, 0x07, 0xf5, 0x05, 0xd3, 0x39, 0xf2, 0x03, + 0x45, 0x86, 0x61, 0xc8, 0x3a, 0x9a, 0x5a, 0x27, 0xaa, 0x48, 0xb5, 0xec, 0x47, 0xf8, + 0xd6, 0x0d, 0x2a, 0x41, 0x00, 0x1f, 0xce, 0x30, 0xff, 0x75, 0x3a, 0x8a, 0x8c, 0xe4, + 0x92, 0xef, 0xcd, 0x1f, 0x75, 0x3b, 0x7f, 0x4a, 0xd7, 0x36, 0x62, 0x64, 0x47, 0xd1, + 0xb6, 0xf0, 0x7a, 0x61, 0x7d, 0x4b, 0xfc, 0xdb, 0x48, 0xaf, 0xef, 0x08, 0x2d, 0xae, + 0x1d, 0x76, 0x54, 0x4e, 0x8b, 0x63, 0xad, 0xcb, 0xb6, 0x0e, 0x14, 0x96, 0x69, 0x32, + 0x60, 0xc7, 0x20, 0xe6, 0x72, 0x1e, 0x00, 0x20, 0xef, 0xa3, 0xf8, 0xd8, 0x8d, 0x15, + 0xb5, 0xaa, 0x48, 0xa1, 0xb2, 0x2c, ], ock: [ - 0x91, 0x36, 0x59, 0x30, 0x9e, 0xcf, 0xcd, 0xfd, 0x7e, 0x0c, 0xef, 0x23, 0xf8, 0x80, - 0xae, 0x4c, 0xf4, 0xd8, 0xcf, 0x67, 0x78, 0xb9, 0xc4, 0xe6, 0xf4, 0xc7, 0x71, 0x7b, - 0xf5, 0xca, 0xf0, 0x9e, + 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, + 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, + 0x09, 0xd0, 0x15, 0xac, ], op: [ 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, - 0x4a, 0xd7, 0xc7, 0x84, 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, - 0x4d, 0x80, 0x4a, 0x17, 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, - 0x92, 0x1c, 0xd5, 0xda, 0x8a, 0x6e, 0x1a, 0x08, + 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, + 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, + 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, ], c_out: [ - 0x4d, 0xf8, 0xda, 0x22, 0xec, 0x17, 0xf4, 0x16, 0xe0, 0x59, 0x1a, 0xac, 0xc1, 0x6b, - 0x6d, 0xd2, 0xbb, 0xbf, 0x47, 0xbe, 0x04, 0x30, 0x3d, 0xc8, 0x85, 0xd3, 0x5a, 0xc3, - 0xf9, 0x92, 0x3e, 0xea, 0x41, 0xf3, 0x6b, 0x3a, 0x4a, 0x5c, 0x5e, 0x73, 0x3e, 0x32, - 0x6e, 0x96, 0xdb, 0xe5, 0x5e, 0xf9, 0xe7, 0xe8, 0x42, 0x27, 0x0c, 0xbf, 0x46, 0x7c, - 0xdc, 0x16, 0x0e, 0xbf, 0x4f, 0x10, 0x9a, 0xd6, 0x92, 0x0a, 0x6a, 0xed, 0x4a, 0x01, - 0x71, 0xd9, 0x06, 0xe3, 0xe8, 0x13, 0x32, 0xe6, 0xc5, 0x61, + 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, + 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, + 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, + 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, + 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, + 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, ], }, TestVector { @@ -515,34 +515,34 @@ pub(crate) fn test_vectors() -> Vec { 0xc5, 0xb3, 0x73, 0x3e, ], nf_old: [ - 0xbe, 0xf8, 0xcf, 0x16, 0x98, 0xe4, 0x78, 0x47, 0xd3, 0x8e, 0x1a, 0xaa, 0x88, 0x86, - 0x10, 0x77, 0xcd, 0xb5, 0xad, 0x4c, 0xf6, 0x6f, 0xe4, 0x2f, 0xd6, 0x52, 0x57, 0x81, - 0xb6, 0xd3, 0x4f, 0x1e, + 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, + 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, + 0x25, 0xb9, 0xff, 0x16, ], cmx: [ - 0xd8, 0x19, 0xa6, 0x37, 0x7a, 0xce, 0x33, 0xf9, 0x21, 0xf2, 0x29, 0xf9, 0x32, 0x86, - 0x6d, 0x9f, 0xcd, 0xb9, 0xd0, 0x42, 0x6a, 0xfa, 0xca, 0x9e, 0x60, 0x50, 0xb4, 0x7a, - 0x83, 0x19, 0xd6, 0x0d, + 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, + 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, + 0xe0, 0x24, 0x69, 0x05, ], esk: [ - 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, 0xb3, 0x5d, 0xa9, 0xc6, - 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, 0xec, 0x8a, 0xd7, 0xf7, - 0x4c, 0xd9, 0xb2, 0x1b, + 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, + 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, + 0x59, 0xe0, 0x4c, 0x3a, ], ephemeral_key: [ - 0x5b, 0xcb, 0xf9, 0xf1, 0xd7, 0xdd, 0x68, 0xe7, 0xcc, 0x6d, 0x6c, 0x78, 0x49, 0x50, - 0xd1, 0xc2, 0xe0, 0xbe, 0x6a, 0x84, 0xa7, 0xa8, 0x8d, 0x6f, 0x7a, 0x20, 0x98, 0xc3, - 0xdc, 0xae, 0x3f, 0x2f, + 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, + 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, + 0x86, 0x6b, 0xce, 0x23, ], shared_secret: [ - 0x37, 0x35, 0x1c, 0xe2, 0x57, 0xb2, 0x79, 0x4d, 0x86, 0xa5, 0x3d, 0x26, 0x8d, 0xc9, - 0x00, 0x06, 0x40, 0xc2, 0x76, 0xf3, 0xf4, 0x65, 0xe1, 0xaa, 0x70, 0xbf, 0xde, 0xf4, - 0x99, 0xa3, 0xd7, 0xaa, + 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, + 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, + 0xe2, 0x62, 0xd3, 0xb6, ], k_enc: [ - 0xea, 0x22, 0x99, 0x65, 0x39, 0xd3, 0x74, 0xda, 0x6a, 0x75, 0x34, 0x39, 0x5a, 0xe9, - 0x23, 0x36, 0xfc, 0xa7, 0x85, 0x11, 0x20, 0xdd, 0x1a, 0xe4, 0x9e, 0x45, 0xb3, 0x3e, - 0x0b, 0xed, 0xe9, 0xac, + 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, + 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, + 0x0c, 0xdd, 0x5a, 0xa6, ], p_enc: [ 0x02, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, @@ -588,68 +588,68 @@ pub(crate) fn test_vectors() -> Vec { 0x55, 0x21, 0x93, 0xb1, ], c_enc: [ - 0x12, 0xd6, 0x64, 0xed, 0x05, 0xd6, 0x46, 0x26, 0x89, 0xd4, 0xf2, 0x4a, 0xee, 0x5a, - 0x4f, 0x0f, 0x32, 0x35, 0xff, 0x11, 0x0b, 0x2d, 0xf9, 0x9f, 0x67, 0xd8, 0xc5, 0xb3, - 0x68, 0xdd, 0x47, 0x69, 0xd8, 0x44, 0xd3, 0xdd, 0xa0, 0x3f, 0x58, 0xc5, 0x48, 0x63, - 0x62, 0xe8, 0x90, 0x81, 0xa5, 0xdf, 0xd0, 0xa6, 0x06, 0xa3, 0x91, 0x26, 0x4b, 0x56, - 0xca, 0x3a, 0xfc, 0x4f, 0xe0, 0xe4, 0xc3, 0x05, 0xf3, 0x07, 0x78, 0x09, 0x4a, 0x00, - 0xb7, 0x33, 0x4b, 0xdd, 0x82, 0x45, 0xac, 0x56, 0x0e, 0xf3, 0x29, 0xbc, 0x68, 0x97, - 0xd4, 0xd7, 0xba, 0x31, 0xac, 0x84, 0x54, 0x44, 0x1a, 0x15, 0xc8, 0xd3, 0xce, 0xcc, - 0x71, 0x32, 0xdf, 0x0d, 0x9d, 0x0e, 0xcf, 0x92, 0x84, 0x34, 0xa0, 0xd2, 0x8c, 0x1b, - 0x00, 0x48, 0x52, 0x01, 0xec, 0x33, 0xbe, 0x9a, 0x28, 0x74, 0xb4, 0x29, 0x6c, 0x04, - 0x22, 0xc7, 0xe7, 0xa0, 0xa3, 0xa2, 0x2e, 0xc7, 0xe7, 0x21, 0xa4, 0x79, 0x22, 0x8d, - 0xa2, 0x8b, 0x47, 0x37, 0xaf, 0x52, 0x06, 0xdf, 0x7d, 0x74, 0xe4, 0x84, 0xc4, 0xf7, - 0xa8, 0x56, 0xbe, 0x8c, 0xd0, 0x4b, 0x21, 0x26, 0xb5, 0x27, 0x11, 0xe7, 0xb0, 0xaf, - 0x75, 0xc7, 0x52, 0x84, 0xa1, 0x57, 0x20, 0x40, 0xe8, 0xad, 0xe5, 0x85, 0xe8, 0xa4, - 0x82, 0x80, 0x03, 0x59, 0x67, 0x46, 0xc4, 0x0c, 0x9d, 0x76, 0x0d, 0x92, 0x74, 0xb1, - 0x25, 0x42, 0x2b, 0x63, 0x48, 0x1a, 0x17, 0xff, 0xba, 0xb8, 0xc2, 0xde, 0x13, 0xb2, - 0x19, 0xf5, 0x8a, 0x35, 0x95, 0x2d, 0x88, 0x7a, 0xed, 0xe8, 0xe0, 0x2f, 0x10, 0x33, - 0x8c, 0x23, 0x98, 0x23, 0xfb, 0x43, 0x49, 0x51, 0x84, 0x47, 0x12, 0xf6, 0x8d, 0x6e, - 0x4f, 0xef, 0xae, 0x2b, 0x79, 0x5b, 0xa9, 0x78, 0xe9, 0x81, 0xc1, 0x09, 0x27, 0xab, - 0xbc, 0x16, 0x30, 0x66, 0xa0, 0xe9, 0x60, 0xb3, 0xb8, 0xa3, 0x26, 0xc0, 0x39, 0x85, - 0x81, 0x10, 0x93, 0x99, 0xf6, 0xed, 0x60, 0x44, 0x9a, 0xa8, 0x58, 0xd5, 0xdd, 0x27, - 0xdb, 0xf8, 0x89, 0x9f, 0x9c, 0x9a, 0x50, 0x20, 0x5f, 0x25, 0xd0, 0xcc, 0x50, 0xb2, - 0xde, 0xe3, 0x63, 0x54, 0xc5, 0xe4, 0x48, 0x4d, 0x36, 0xf6, 0x3c, 0x97, 0x63, 0xd8, - 0x41, 0xad, 0x5e, 0x00, 0x21, 0x63, 0x6a, 0x85, 0x7c, 0xfb, 0x79, 0xa5, 0x12, 0x3c, - 0x3d, 0xfb, 0x77, 0x3d, 0x0c, 0x1b, 0xeb, 0x9f, 0x90, 0xa9, 0x72, 0xd0, 0xfc, 0x80, - 0x5f, 0x65, 0x5d, 0x69, 0x40, 0x85, 0x23, 0xb9, 0x9b, 0x62, 0xa8, 0xfa, 0xbe, 0xf0, - 0xc0, 0x24, 0xf2, 0x1f, 0x50, 0xe4, 0xc1, 0x12, 0xe2, 0xfe, 0xdd, 0x58, 0xca, 0xe9, - 0x60, 0x9a, 0xc6, 0xf7, 0xcc, 0x79, 0x83, 0x86, 0xc9, 0xd9, 0x06, 0x42, 0x1c, 0xa5, - 0x7c, 0xf8, 0x1b, 0x09, 0x6b, 0xba, 0xda, 0x64, 0xd0, 0xee, 0x76, 0x95, 0x18, 0x9d, - 0x5f, 0xb1, 0x7a, 0xe2, 0x53, 0x1d, 0xbb, 0x2c, 0x00, 0x58, 0x5a, 0x26, 0xa6, 0x8c, - 0x27, 0xf9, 0x77, 0x77, 0x84, 0x1a, 0x3e, 0x39, 0x30, 0xc7, 0x0f, 0xc3, 0xfa, 0x8e, - 0x2b, 0x7f, 0xc2, 0x1e, 0x87, 0xcf, 0x9f, 0x63, 0xb3, 0x63, 0xb8, 0x8d, 0xaa, 0x1f, - 0xb6, 0x7b, 0xda, 0xe8, 0xe5, 0x5b, 0x68, 0x51, 0x6d, 0x19, 0xdf, 0xef, 0xec, 0x9b, - 0x3d, 0x38, 0xe6, 0xe1, 0xd0, 0xa6, 0xe4, 0x51, 0xd6, 0xd1, 0xf5, 0x2d, 0x1f, 0x96, - 0xdd, 0x0d, 0x53, 0x6d, 0x68, 0xd2, 0x69, 0x86, 0x70, 0x9f, 0x41, 0xe7, 0x60, 0x74, - 0x05, 0x5b, 0xf7, 0x52, 0xbf, 0x38, 0x86, 0x92, 0xc8, 0x2c, 0xfd, 0xa1, 0xeb, 0xb0, - 0x17, 0x8b, 0x8e, 0x0c, 0x85, 0xad, 0x7b, 0x15, 0x99, 0x14, 0x42, 0x8e, 0x30, 0x21, - 0xda, 0xe3, 0x01, 0x0d, 0x65, 0x6c, 0x10, 0x36, 0xf4, 0xa5, 0x7e, 0x7f, 0xad, 0xe0, - 0xfc, 0x32, 0x2a, 0xa6, 0xfd, 0xde, 0x71, 0x4a, 0x8c, 0x53, 0x78, 0x79, 0xe7, 0x04, - 0x41, 0x6f, 0x51, 0x04, 0xdb, 0xbc, 0x8f, 0xf2, 0x42, 0xc1, 0x6d, 0x2d, 0xf4, 0xa8, - 0x41, 0xeb, 0x6b, 0x45, 0x3a, 0x12, 0x83, 0xf6, 0x5f, 0xe1, 0x0d, 0x70, 0xc8, 0x76, - 0x41, 0x8e, 0x44, 0x4a, 0xb3, 0x1b, 0x93, 0x71, 0xa2, 0x7d, 0x36, 0xd8, 0x6e, 0x8f, - 0x1c, 0x32, 0x77, 0xca, 0xfd, 0xf8, + 0x81, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, + 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, + 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, + 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0xa4, 0xd7, 0x1d, 0x1a, + 0xb1, 0x08, 0x09, 0x6e, 0x76, 0x08, 0x91, 0xd5, 0x31, 0x07, 0xf0, 0x3d, 0xea, 0x4a, + 0xe8, 0xe4, 0xd3, 0xfe, 0xbd, 0x98, 0x77, 0xf8, 0x57, 0x0a, 0xa3, 0x09, 0xd0, 0x97, + 0xd4, 0x23, 0xbb, 0x76, 0x3f, 0xb3, 0xe7, 0xe9, 0xbe, 0x3c, 0x8f, 0xa0, 0x34, 0xc0, + 0x1d, 0x66, 0x4f, 0x47, 0xa0, 0xe7, 0x13, 0x3c, 0xa1, 0x1a, 0x48, 0xcd, 0x0e, 0xea, + 0x46, 0x35, 0xfa, 0x77, 0x25, 0x0a, 0x17, 0xbd, 0xf7, 0xb7, 0x32, 0xc8, 0x98, 0x46, + 0x51, 0x57, 0x4f, 0xd4, 0xf9, 0x9f, 0x7a, 0xa0, 0xdb, 0x28, 0xc2, 0x97, 0x31, 0x52, + 0xbf, 0x42, 0x6e, 0xe9, 0xa4, 0xd8, 0x41, 0xa9, 0x1d, 0x5d, 0x33, 0x57, 0x18, 0xee, + 0xcb, 0xc9, 0xc8, 0xb2, 0xa2, 0x00, 0x15, 0x70, 0xfe, 0x8b, 0x77, 0x91, 0x43, 0xdf, + 0x22, 0x95, 0x98, 0xa5, 0xbe, 0x25, 0x48, 0xcf, 0x35, 0x84, 0x25, 0x18, 0xcc, 0x1d, + 0xbc, 0x78, 0xcc, 0x2f, 0x0f, 0xc8, 0xea, 0x35, 0x7c, 0xe6, 0xc1, 0x7e, 0xb9, 0x7c, + 0x61, 0x38, 0xd5, 0x3e, 0x6c, 0x8e, 0x00, 0xf0, 0x7f, 0x80, 0x01, 0x25, 0x18, 0x2b, + 0x25, 0xa5, 0xe8, 0x75, 0xc5, 0x37, 0x72, 0x09, 0x52, 0x72, 0x22, 0x37, 0x1f, 0x72, + 0xbf, 0xbd, 0x46, 0x28, 0x44, 0xab, 0x06, 0xf3, 0xb3, 0xa1, 0xeb, 0xa3, 0x44, 0x23, + 0xb6, 0x9a, 0xbf, 0x5d, 0xe6, 0x64, 0xba, 0x83, 0xcd, 0x43, 0xb6, 0xa8, 0xe9, 0xd5, + 0xb7, 0xc5, 0x2a, 0xdb, 0x86, 0x15, 0x04, 0x1b, 0x90, 0xd9, 0x08, 0x83, 0x1a, 0x6f, + 0xf9, 0x2d, 0xb4, 0x8a, 0x14, 0xac, 0x4d, 0xfa, 0x67, 0xd0, 0x2c, 0x72, 0xe0, 0xc8, + 0x63, 0x15, 0x7d, 0x98, 0xf8, 0xf5, 0x45, 0x37, 0x92, 0x97, 0x43, 0xc9, 0x69, 0xbc, + 0x91, 0xc2, 0xc1, 0x37, 0x52, 0x04, 0x98, 0x3c, 0x99, 0x99, 0x97, 0x5f, 0xfa, 0x5e, + 0xe5, 0xfe, 0x1f, 0x69, 0x71, 0x99, 0x40, 0x5f, 0x09, 0x66, 0xe3, 0x1f, 0x34, 0xe1, + 0x52, 0x38, 0x44, 0x38, 0x18, 0x44, 0x98, 0x2b, 0x2c, 0x3b, 0x49, 0xa2, 0x09, 0xff, + 0xa3, 0xce, 0xe9, 0x79, 0xa8, 0x5b, 0x19, 0xb8, 0x50, 0xf4, 0x1d, 0xcc, 0xc4, 0x63, + 0xe2, 0x2e, 0x24, 0xa3, 0x04, 0x9d, 0x37, 0xb1, 0xfb, 0x37, 0x0d, 0xeb, 0xdd, 0xf4, + 0xde, 0x05, 0x46, 0x24, 0x5e, 0x4f, 0x02, 0xa9, 0x84, 0x98, 0xaf, 0x53, 0x2e, 0x27, + 0xac, 0xae, 0x5c, 0x7e, 0xd1, 0x43, 0xe6, 0xe9, 0xcc, 0xfa, 0x74, 0x35, 0x16, 0x02, + 0x16, 0x57, 0xac, 0xb2, 0x5e, 0x44, 0x47, 0x84, 0x5c, 0x5f, 0x9c, 0x59, 0x64, 0x60, + 0x7c, 0x4a, 0x78, 0x72, 0x1d, 0x98, 0x1a, 0x7f, 0xf2, 0xfd, 0xf6, 0xc0, 0x33, 0x62, + 0x8b, 0xff, 0xd6, 0xf0, 0xb8, 0xde, 0x0c, 0xd6, 0x35, 0xec, 0x22, 0xf8, 0xb5, 0x0e, + 0xd6, 0x37, 0xfe, 0x4e, 0x00, 0xf9, 0xd3, 0xc3, 0xd4, 0xf1, 0x81, 0x0b, 0x09, 0xb7, + 0x5c, 0x96, 0xe2, 0xfc, 0xf1, 0x11, 0x85, 0x31, 0x7e, 0xdf, 0xa3, 0x9d, 0x19, 0x25, + 0xde, 0xd8, 0x14, 0xdd, 0xe0, 0xef, 0x00, 0xa3, 0xfb, 0x47, 0xaf, 0x5d, 0x81, 0x20, + 0x94, 0xaf, 0x13, 0xd0, 0x1c, 0x98, 0x56, 0x9f, 0xf7, 0x73, 0x57, 0x87, 0xfa, 0x9b, + 0xd0, 0x1f, 0xa0, 0x69, 0x28, 0x27, 0x5f, 0xdd, 0x10, 0x38, 0x96, 0x5f, 0xb0, 0x6f, + 0xb3, 0x5e, 0xdb, 0x73, 0x80, 0xdd, 0x3c, 0x42, 0x41, 0x9e, 0x0c, 0x0e, 0xde, 0x4c, + 0x48, 0x6a, 0x9d, 0xb4, 0x95, 0x38, 0x86, 0xae, 0xc6, 0xad, 0x30, 0x70, 0x28, 0xeb, + 0x26, 0xa3, 0x7e, 0xf4, 0x71, 0x56, 0x7a, 0xd4, 0xbd, 0x4e, 0xaa, 0xb7, 0xa8, 0x2c, + 0xb0, 0xd6, 0xb5, 0xf0, 0x5e, 0x89, 0x4e, 0x53, 0x25, 0x82, 0x1d, 0x92, 0xbe, 0xd2, + 0xb8, 0x6f, 0xb2, 0x43, 0x37, 0xd5, 0x79, 0x28, 0x8f, 0x6d, 0xf7, 0x34, 0x77, 0x1d, + 0x9e, 0xf8, 0x35, 0x8b, 0xa9, 0x1a, ], ock: [ - 0xca, 0x6f, 0x98, 0xe6, 0xcf, 0x9f, 0xc3, 0x6a, 0xf5, 0xf6, 0x98, 0x82, 0x74, 0x2d, - 0x06, 0xec, 0x5d, 0x29, 0xac, 0x2a, 0x02, 0x89, 0x44, 0xa2, 0x01, 0x89, 0xd5, 0x1c, - 0x8a, 0x9b, 0xdc, 0xd6, + 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, + 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, + 0xfa, 0x2e, 0xfd, 0xe8, ], op: [ 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, - 0x15, 0x37, 0x14, 0x0d, 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, - 0xb3, 0x5d, 0xa9, 0xc6, 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, - 0xec, 0x8a, 0xd7, 0xf7, 0x4c, 0xd9, 0xb2, 0x1b, + 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, + 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, + 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, ], c_out: [ - 0xa9, 0x5e, 0x1a, 0x22, 0x45, 0x65, 0x29, 0x5e, 0x9b, 0x55, 0x3a, 0xdd, 0xe8, 0xb0, - 0x14, 0x47, 0x5c, 0x68, 0x7b, 0x5d, 0x13, 0x49, 0xc1, 0xdf, 0x8a, 0xd4, 0xb7, 0xcf, - 0xd3, 0xdf, 0xc1, 0x00, 0x6c, 0x7c, 0x37, 0xde, 0x67, 0x6d, 0x6f, 0xde, 0x31, 0x8e, - 0x2f, 0xdf, 0xcc, 0x2e, 0x2e, 0x23, 0x2c, 0xc5, 0xf8, 0x85, 0x28, 0x39, 0xe7, 0xef, - 0xab, 0x8b, 0x20, 0x0e, 0xbc, 0x6a, 0x4d, 0xf8, 0x2a, 0x75, 0x21, 0xce, 0x0f, 0x38, - 0x4f, 0xe2, 0x7a, 0x0d, 0xec, 0x59, 0xe9, 0xd2, 0xc0, 0xe3, + 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, + 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, + 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, + 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, + 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, + 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, ], }, TestVector { @@ -724,34 +724,34 @@ pub(crate) fn test_vectors() -> Vec { 0x32, 0xb5, 0x0e, 0x96, ], nf_old: [ - 0x18, 0x89, 0x8e, 0x75, 0x21, 0x7b, 0x32, 0x9b, 0x3a, 0x56, 0x7b, 0x09, 0x37, 0x89, - 0xa4, 0xd8, 0x19, 0xcd, 0xb0, 0x34, 0x88, 0xb8, 0x10, 0xda, 0x22, 0x0c, 0x3f, 0x59, - 0xba, 0x03, 0x39, 0x26, + 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, + 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, + 0xf5, 0x0e, 0x92, 0x37, ], cmx: [ - 0x23, 0xad, 0xc3, 0xbf, 0x35, 0x0e, 0xb0, 0x84, 0xbd, 0x28, 0xbc, 0x2d, 0xcf, 0xb7, - 0x98, 0x3f, 0xf6, 0xb3, 0xb6, 0xf2, 0xeb, 0x2d, 0x6f, 0x12, 0x4f, 0xfc, 0x46, 0x85, - 0xab, 0xe8, 0xde, 0x3a, + 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, + 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, + 0xb1, 0x41, 0x41, 0x30, ], esk: [ - 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, 0x2c, 0xf1, 0xb8, 0x88, - 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, 0x98, 0x02, 0xf1, 0x53, - 0x6a, 0x9e, 0x9f, 0x2b, + 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, + 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, + 0xcb, 0x52, 0xa6, 0x13, ], ephemeral_key: [ - 0x91, 0xaf, 0x13, 0x8e, 0xd9, 0x95, 0x44, 0x66, 0x95, 0x16, 0x1b, 0x14, 0x2d, 0xc2, - 0xde, 0x59, 0xac, 0x23, 0x05, 0xec, 0xbe, 0xc6, 0x29, 0x33, 0xf5, 0x2f, 0x2a, 0xa1, - 0xf9, 0xb2, 0x71, 0x86, + 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, + 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, + 0x0a, 0x2c, 0x60, 0x98, ], shared_secret: [ - 0xe1, 0xd3, 0xaf, 0x73, 0x6a, 0xb9, 0xc6, 0x11, 0x6f, 0x46, 0x8f, 0x91, 0x66, 0x80, - 0x63, 0x20, 0x35, 0x0f, 0x7e, 0x73, 0x51, 0x3b, 0xa6, 0x05, 0x50, 0xeb, 0x2d, 0xf0, - 0x1f, 0xf7, 0x83, 0x2d, + 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, + 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, + 0x2f, 0x7b, 0x3b, 0x36, ], k_enc: [ - 0xb4, 0x3e, 0x43, 0x3e, 0x16, 0x45, 0xeb, 0x51, 0x5e, 0x4a, 0x4c, 0x7d, 0x10, 0xc9, - 0x3d, 0x08, 0xf2, 0xf1, 0xc3, 0x30, 0x95, 0xbf, 0x8c, 0x80, 0x0a, 0x04, 0x17, 0x62, - 0xab, 0x5c, 0xf8, 0x2c, + 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, + 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, + 0xdf, 0x21, 0x73, 0x73, ], p_enc: [ 0x02, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, @@ -797,68 +797,68 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x65, 0x57, 0x53, ], c_enc: [ - 0x27, 0x62, 0x0d, 0xf5, 0xdb, 0x17, 0x76, 0x6e, 0xbd, 0x9a, 0x99, 0xd6, 0x9a, 0x9a, - 0x49, 0x38, 0x73, 0x21, 0xf0, 0xc9, 0x47, 0x25, 0x23, 0x57, 0xb5, 0xb7, 0x48, 0x49, - 0x38, 0xe3, 0xf5, 0xff, 0x9f, 0x32, 0x0e, 0x80, 0x6c, 0x4b, 0x54, 0xc3, 0x6e, 0x41, - 0x2e, 0x8a, 0x6e, 0xad, 0xe3, 0x5b, 0x83, 0x01, 0xf7, 0x34, 0xf3, 0x71, 0x2e, 0x6a, - 0xac, 0xe6, 0x99, 0xf5, 0x9e, 0x11, 0x2a, 0x7b, 0xf5, 0x44, 0x59, 0xdc, 0x5d, 0x9f, - 0x7b, 0xbf, 0x3b, 0x9f, 0x74, 0x6c, 0x45, 0xbb, 0xed, 0x69, 0xa4, 0x25, 0x1b, 0x29, - 0xf3, 0xd2, 0x15, 0xc2, 0x9f, 0x76, 0x1c, 0x7d, 0x05, 0x88, 0x19, 0xf0, 0xdd, 0x4e, - 0x70, 0x71, 0xb0, 0x77, 0xcb, 0x00, 0xcb, 0x93, 0x62, 0xa4, 0x98, 0x16, 0x88, 0x0d, - 0x49, 0xb7, 0x11, 0xf9, 0x20, 0x65, 0xf1, 0x53, 0x2e, 0x58, 0x18, 0x0b, 0xbd, 0xb4, - 0x91, 0xdb, 0xbb, 0x96, 0x8a, 0x09, 0xb5, 0x63, 0xce, 0x1d, 0x29, 0x87, 0x6f, 0xd0, - 0x52, 0x6d, 0x65, 0xda, 0x67, 0x27, 0xad, 0x40, 0xf9, 0x64, 0x02, 0xf9, 0x9a, 0xa5, - 0xac, 0x06, 0x42, 0x51, 0xc4, 0x65, 0xe3, 0xc7, 0xdb, 0x1f, 0xfe, 0xef, 0xac, 0xd7, - 0xf5, 0x1b, 0xa4, 0xf1, 0x9c, 0x6c, 0x17, 0x87, 0xa0, 0xff, 0xb4, 0x9d, 0xbb, 0x7b, - 0x0a, 0x2b, 0x15, 0x64, 0x03, 0xd6, 0x6c, 0x22, 0x13, 0xe5, 0x1d, 0x58, 0xea, 0xef, - 0xe8, 0x6d, 0x5d, 0xef, 0x0d, 0x24, 0xb7, 0xf2, 0xf8, 0xc1, 0x10, 0x32, 0x9a, 0x3a, - 0x73, 0xcb, 0x33, 0x50, 0x14, 0x0e, 0x6b, 0xf7, 0x2c, 0xb6, 0xaa, 0x22, 0x2d, 0xef, - 0x5a, 0x47, 0xe2, 0x1a, 0xf0, 0xb9, 0xae, 0xeb, 0x74, 0x8c, 0x01, 0xc6, 0x7a, 0xb6, - 0xc9, 0xfd, 0x6e, 0x53, 0x6a, 0x0d, 0x92, 0x76, 0x61, 0x51, 0xb1, 0xac, 0x7c, 0xc9, - 0x85, 0x5c, 0xa9, 0x8d, 0xea, 0x74, 0x85, 0x14, 0xef, 0xee, 0x89, 0xe8, 0x9a, 0x01, - 0x68, 0xf5, 0xdd, 0xf4, 0xac, 0x2b, 0x7c, 0xe1, 0xc9, 0xc2, 0x92, 0xfb, 0xef, 0x2f, - 0x45, 0x51, 0xa8, 0x88, 0xc3, 0x34, 0x5c, 0x65, 0x92, 0x30, 0x39, 0xfc, 0x21, 0xf7, - 0x31, 0x55, 0x9b, 0xd9, 0x24, 0xbc, 0x2c, 0x15, 0x5b, 0xc0, 0xbe, 0x80, 0x38, 0x4a, - 0x9e, 0x49, 0xbd, 0xa6, 0x9a, 0x70, 0x6b, 0x1a, 0xd6, 0xa2, 0x62, 0xab, 0xc6, 0x26, - 0x50, 0x77, 0x2f, 0xd7, 0xea, 0xbc, 0x3f, 0x75, 0xa9, 0xac, 0xca, 0xa2, 0x8b, 0xcd, - 0xea, 0x65, 0xf9, 0x4e, 0x16, 0xcc, 0x3d, 0x05, 0x38, 0xe5, 0x49, 0x86, 0x0a, 0x60, - 0x12, 0x5b, 0xb4, 0xbc, 0x0c, 0x23, 0xe3, 0x22, 0x27, 0x68, 0x2c, 0x09, 0xb5, 0xaa, - 0x30, 0x4a, 0x16, 0x09, 0x2a, 0xd4, 0xa3, 0xe2, 0xf6, 0x28, 0x3c, 0x38, 0x51, 0x80, - 0x6e, 0x72, 0x17, 0x3f, 0x7d, 0x32, 0x97, 0xed, 0x92, 0xe5, 0x32, 0x40, 0x39, 0xa7, - 0x31, 0x4f, 0x5f, 0xb7, 0x38, 0x6e, 0x09, 0x94, 0xf5, 0x2f, 0x8c, 0xcc, 0xf1, 0x87, - 0xd6, 0x20, 0x41, 0x0c, 0xce, 0x9d, 0x0b, 0x91, 0x93, 0xac, 0xec, 0x6d, 0x4c, 0x9b, - 0xd3, 0x4e, 0x08, 0x80, 0x58, 0x0a, 0xbe, 0xae, 0xd9, 0x7c, 0xb7, 0x80, 0x0f, 0x6a, - 0xbc, 0x67, 0xc2, 0x5c, 0x49, 0x19, 0x2e, 0x37, 0xdc, 0xf3, 0x3d, 0x1a, 0x59, 0x16, - 0x47, 0x5a, 0xe9, 0x99, 0x90, 0xd8, 0x29, 0xc1, 0xd5, 0x9e, 0x69, 0x2f, 0x47, 0x36, - 0x93, 0xbc, 0xe3, 0x58, 0x5a, 0xec, 0xd3, 0xc1, 0x3b, 0xae, 0x15, 0xcb, 0xef, 0xf2, - 0x98, 0x52, 0x2a, 0xab, 0xf4, 0x6b, 0xea, 0x3a, 0xbf, 0x63, 0x30, 0xa5, 0x6e, 0x37, - 0x24, 0x51, 0x81, 0x32, 0xce, 0x94, 0x39, 0x41, 0x6a, 0x28, 0xe9, 0x52, 0x0d, 0xdf, - 0x64, 0x17, 0x00, 0xb4, 0x6f, 0x37, 0x49, 0x50, 0xf3, 0x27, 0xaf, 0x3d, 0x0b, 0x3d, - 0x3b, 0x3f, 0x61, 0xa8, 0x84, 0xcf, 0x4f, 0x82, 0x02, 0x56, 0xfb, 0x91, 0x65, 0xdc, - 0xa0, 0xe4, 0x32, 0x60, 0xfc, 0xb5, 0x63, 0xef, 0x1a, 0xb4, 0xe7, 0x12, 0xef, 0x07, - 0x23, 0xd6, 0x75, 0x90, 0xa4, 0xff, 0xc3, 0x66, 0xc4, 0xa7, 0x92, 0x50, 0x29, 0x93, - 0x1b, 0xf0, 0x87, 0x3d, 0xac, 0xaa, 0xe9, 0x38, 0x5d, 0x9a, 0xd9, 0x1a, 0xed, 0x75, - 0x93, 0x9d, 0x8b, 0xd1, 0xaf, 0x5d, + 0xe7, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, + 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, + 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, + 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0x34, 0xc1, 0x40, 0xce, + 0x93, 0x40, 0x19, 0xb2, 0xea, 0xa8, 0xea, 0x84, 0x35, 0x80, 0xb3, 0x5f, 0x14, 0xea, + 0x51, 0x92, 0xde, 0x8a, 0x12, 0xf9, 0xab, 0xc9, 0x06, 0x10, 0x15, 0xe1, 0x47, 0x9e, + 0xf9, 0x8d, 0x19, 0xa5, 0x34, 0xe9, 0xe4, 0x61, 0x64, 0xc3, 0xca, 0xc4, 0xeb, 0x54, + 0x26, 0x4c, 0xed, 0xcd, 0x83, 0xaf, 0xc2, 0xac, 0x2e, 0x08, 0x7e, 0x39, 0xdf, 0xba, + 0xe7, 0x6b, 0xd5, 0x50, 0xcc, 0x64, 0xa4, 0x04, 0xd2, 0x0c, 0x22, 0xca, 0x00, 0x3b, + 0xf7, 0x5b, 0x12, 0xfb, 0xb8, 0xc7, 0x15, 0x13, 0x72, 0x70, 0x0b, 0x43, 0x9b, 0x3e, + 0x06, 0x57, 0xec, 0xc3, 0x07, 0x70, 0x8f, 0xc3, 0x74, 0x94, 0xbd, 0x06, 0x39, 0xe8, + 0xe1, 0xea, 0xea, 0x37, 0x8f, 0x27, 0xa1, 0x35, 0x74, 0xb7, 0x1f, 0xa4, 0x88, 0x3b, + 0x80, 0x71, 0x2c, 0x7b, 0xeb, 0x5c, 0x30, 0x5f, 0x8d, 0x67, 0xe9, 0x19, 0x97, 0xf8, + 0x03, 0x19, 0xdd, 0xb1, 0x15, 0xb9, 0x51, 0x23, 0x89, 0x7a, 0xae, 0x5f, 0x2d, 0x14, + 0xff, 0xcf, 0xac, 0x7f, 0x65, 0x49, 0xca, 0x54, 0x8f, 0x6e, 0xab, 0xdf, 0x74, 0x81, + 0x70, 0x27, 0xd4, 0x2d, 0x92, 0xd5, 0xcd, 0xf8, 0x8e, 0xd8, 0xd5, 0x11, 0xd1, 0xb5, + 0xc4, 0x32, 0x2f, 0x77, 0x79, 0x74, 0x88, 0x6c, 0x0e, 0xd0, 0x13, 0x99, 0x18, 0x0a, + 0xfa, 0x59, 0x7d, 0xd2, 0xb7, 0x7c, 0x58, 0xb2, 0x7c, 0x8a, 0x61, 0x20, 0x69, 0xe3, + 0x86, 0xad, 0x63, 0x4c, 0xb0, 0x17, 0xa8, 0xe9, 0xf4, 0x8e, 0x37, 0xc4, 0x3e, 0xe8, + 0x73, 0x3a, 0x0a, 0xcb, 0x69, 0xf8, 0xed, 0x9f, 0x6f, 0x30, 0x5f, 0x3b, 0xd1, 0xe9, + 0x82, 0xb9, 0x4b, 0x1e, 0x51, 0xf4, 0xba, 0x98, 0x5b, 0x20, 0xec, 0x97, 0x4a, 0xc9, + 0xa7, 0x93, 0xaa, 0x26, 0x4d, 0x61, 0x5b, 0x9d, 0xea, 0x48, 0x59, 0xa4, 0xd4, 0xca, + 0xa7, 0x0d, 0x7a, 0x6b, 0x65, 0x30, 0x76, 0x85, 0xab, 0x53, 0x4e, 0x54, 0x55, 0x63, + 0x1f, 0x6d, 0x68, 0xa4, 0x51, 0xd8, 0xaf, 0x2d, 0x41, 0x82, 0x52, 0x80, 0x0f, 0x68, + 0x42, 0x31, 0xaf, 0xc2, 0x6d, 0x1f, 0xef, 0xc4, 0x03, 0xd7, 0x5f, 0x2e, 0x12, 0x0f, + 0x5b, 0xe2, 0xb6, 0x74, 0x48, 0x60, 0x09, 0x26, 0x7c, 0xbc, 0x0c, 0xb0, 0x01, 0xbb, + 0x47, 0xf0, 0xff, 0x46, 0x97, 0xea, 0xf5, 0x3d, 0xc9, 0x9c, 0x10, 0x77, 0x3a, 0x38, + 0xcd, 0x06, 0xb4, 0x8b, 0xa3, 0x91, 0x19, 0xdb, 0x49, 0x84, 0xd0, 0x9a, 0x5b, 0xde, + 0x13, 0x89, 0x0e, 0xa0, 0x61, 0x3d, 0x0c, 0xe0, 0x04, 0x3e, 0xae, 0x9a, 0x20, 0x89, + 0x14, 0x1f, 0xd9, 0x46, 0x59, 0x13, 0xc1, 0xcc, 0x33, 0x27, 0xa5, 0x59, 0x42, 0xb9, + 0xfd, 0x8f, 0xb8, 0x1c, 0x84, 0x7d, 0x8f, 0xdd, 0xf8, 0xbd, 0xba, 0xcf, 0xa0, 0xfb, + 0x05, 0x52, 0xc1, 0xfe, 0x4c, 0xc4, 0xc0, 0x7f, 0x4d, 0xcf, 0x15, 0x1c, 0x5e, 0x74, + 0xe8, 0xd6, 0x9b, 0x2b, 0x8b, 0xf7, 0xfd, 0x95, 0xec, 0xeb, 0x65, 0x5e, 0x00, 0x53, + 0x58, 0x16, 0xd3, 0x8b, 0x4a, 0x28, 0xd4, 0xa9, 0xae, 0xeb, 0xb6, 0x9a, 0xb4, 0xdd, + 0x12, 0xbf, 0x13, 0xfd, 0x5a, 0x45, 0x9b, 0x6b, 0xb6, 0x83, 0xff, 0xd9, 0xdd, 0x7b, + 0x0d, 0x0c, 0xe7, 0x29, 0x67, 0x75, 0x80, 0x8a, 0x84, 0x3f, 0x3b, 0x8c, 0xc7, 0x89, + 0xfd, 0x5f, 0x43, 0xe0, 0x84, 0xd8, 0x7d, 0x6a, 0xda, 0x8d, 0x1f, 0x28, 0xc2, 0x64, + 0xe6, 0x44, 0xe9, 0xad, 0x96, 0x5c, 0x28, 0x08, 0x8a, 0x52, 0xe4, 0xb3, 0x56, 0x42, + 0xf9, 0xb5, 0xe0, 0x66, 0x49, 0x90, 0x96, 0x3b, 0xc2, 0x3b, 0x9b, 0xb4, 0x8f, 0x46, + 0x74, 0x73, 0x53, 0x58, 0x0e, 0xcc, 0x45, 0x20, 0xcf, 0xf1, 0xfa, 0x7f, 0x8f, 0xbc, + 0x03, 0x0e, 0x64, 0x7d, 0xf1, 0x44, 0xee, 0x6c, 0xa5, 0xb3, 0x16, 0xb3, 0xaf, 0x90, + 0x48, 0x9a, 0x80, 0x9d, 0x9c, 0x9f, ], ock: [ - 0x2a, 0xec, 0x11, 0xd4, 0xae, 0x79, 0x84, 0xe1, 0x69, 0xd1, 0xdf, 0xf1, 0xff, 0x0f, - 0x9a, 0xf5, 0x19, 0x96, 0x34, 0x51, 0xa4, 0x1c, 0x9f, 0x5a, 0xdc, 0x58, 0xe4, 0xf9, - 0x0a, 0xf3, 0x8d, 0x47, + 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, + 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, + 0x3a, 0x5d, 0x91, 0xcb, ], op: [ 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, - 0x14, 0x93, 0x16, 0x36, 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, - 0x2c, 0xf1, 0xb8, 0x88, 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, - 0x98, 0x02, 0xf1, 0x53, 0x6a, 0x9e, 0x9f, 0x2b, + 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, + 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, + 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, ], c_out: [ - 0xe6, 0xeb, 0x22, 0x47, 0xc9, 0x33, 0xe2, 0x4c, 0x9d, 0xf1, 0x28, 0xb1, 0xe0, 0x4e, - 0x8b, 0xc0, 0x5c, 0x65, 0xeb, 0x31, 0x97, 0xdf, 0x9b, 0xa8, 0x70, 0xd8, 0xa0, 0xa1, - 0x8d, 0x9c, 0x24, 0xb7, 0xc9, 0x78, 0xc3, 0x4d, 0x3c, 0x7b, 0xbd, 0x21, 0xe8, 0x7b, - 0x22, 0x39, 0x21, 0x87, 0x54, 0xd9, 0x67, 0x3a, 0x56, 0xa2, 0x73, 0x58, 0x0f, 0x6b, - 0x41, 0xc6, 0x91, 0xe5, 0xfd, 0x30, 0x9c, 0xd5, 0xd1, 0xd2, 0x6d, 0x57, 0x63, 0xa9, - 0xe8, 0xd2, 0x71, 0xc9, 0x77, 0x05, 0x0e, 0x05, 0xdc, 0x96, + 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, + 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, + 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, + 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, + 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, + 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, ], }, TestVector { @@ -933,34 +933,34 @@ pub(crate) fn test_vectors() -> Vec { 0xd2, 0x50, 0x21, 0x17, ], nf_old: [ - 0x23, 0x39, 0xa8, 0x95, 0x29, 0xcf, 0x35, 0x7b, 0x06, 0x7d, 0xd2, 0x8b, 0xe4, 0x06, - 0x6e, 0x16, 0x23, 0x6d, 0xc5, 0xd7, 0x87, 0x06, 0x14, 0x9a, 0x72, 0x8c, 0x3e, 0x3d, - 0x9d, 0xc1, 0x08, 0x1c, + 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, + 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, + 0x3c, 0xfb, 0xf1, 0x31, ], cmx: [ - 0xe3, 0x04, 0xcf, 0x08, 0xc7, 0x86, 0xaf, 0xcb, 0x1d, 0x65, 0x2f, 0x7a, 0x94, 0x17, - 0x29, 0x32, 0x01, 0x51, 0x71, 0x37, 0x93, 0x82, 0x89, 0x42, 0xcb, 0x88, 0xd0, 0x1f, - 0x68, 0x60, 0x4e, 0x1f, + 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, + 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, + 0xc9, 0x65, 0x79, 0x10, ], esk: [ - 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, 0x40, 0xaf, 0x89, 0x3e, - 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, 0x6b, 0x5e, 0xd1, 0xf6, - 0xbf, 0x62, 0xbe, 0x3c, + 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, + 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, + 0x06, 0x15, 0xb2, 0x0d, ], ephemeral_key: [ - 0xdf, 0xe0, 0xf0, 0x0e, 0xb2, 0xb2, 0xf7, 0x08, 0x04, 0x19, 0x1b, 0x5b, 0x2d, 0xdf, - 0x57, 0x8f, 0x6a, 0xda, 0x21, 0x1b, 0x8b, 0x41, 0x7d, 0x95, 0xd2, 0xb7, 0x34, 0xff, - 0xa2, 0x2d, 0x81, 0x30, + 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, + 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, + 0x1b, 0xb1, 0x69, 0x26, ], shared_secret: [ - 0x0e, 0xc6, 0x82, 0xc8, 0xdc, 0x66, 0x41, 0x41, 0x02, 0x4f, 0x92, 0x9d, 0x1a, 0xe5, - 0xd3, 0x9c, 0x39, 0x4d, 0x05, 0xa2, 0x4d, 0xad, 0x0e, 0x4a, 0x6f, 0x94, 0x98, 0xed, - 0x5f, 0x87, 0xd4, 0x88, + 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, + 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, + 0x3a, 0x30, 0x1e, 0x23, ], k_enc: [ - 0xb1, 0x24, 0x5f, 0xb6, 0x37, 0x47, 0xc0, 0x13, 0x39, 0xcd, 0xe8, 0xf9, 0x35, 0x98, - 0xdf, 0xb2, 0xd3, 0x99, 0xec, 0x5e, 0x03, 0xbe, 0xa1, 0x3f, 0x3d, 0xbf, 0x01, 0xca, - 0xdb, 0x93, 0xc9, 0xba, + 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, + 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, + 0xf3, 0x81, 0x58, 0xc4, ], p_enc: [ 0x02, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, @@ -1006,68 +1006,68 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0x6b, 0xa4, 0x80, ], c_enc: [ - 0x31, 0xec, 0x78, 0xd4, 0x02, 0x14, 0xc1, 0xbc, 0x7b, 0x25, 0x94, 0x7b, 0x42, 0xf3, - 0x54, 0x34, 0x60, 0x72, 0x90, 0x27, 0x7c, 0x44, 0xc4, 0x89, 0xe9, 0x38, 0x72, 0x2f, - 0x7c, 0x12, 0xff, 0x55, 0xc4, 0xf1, 0xdf, 0xbe, 0x0f, 0x1a, 0x65, 0xb1, 0x5c, 0x0c, - 0xc4, 0x7a, 0x46, 0xc9, 0xbb, 0x33, 0x5b, 0xd1, 0xa3, 0xe7, 0xe6, 0x62, 0xee, 0x85, - 0x84, 0x57, 0x6b, 0x6f, 0x42, 0x81, 0x95, 0xc9, 0x8c, 0x72, 0xfb, 0x99, 0x75, 0xc7, - 0x17, 0x9c, 0x4c, 0xab, 0x58, 0x66, 0xf5, 0xb4, 0x85, 0x42, 0x8b, 0x50, 0x8e, 0x2e, - 0x05, 0xbe, 0x0c, 0x98, 0x41, 0xa3, 0xa2, 0x91, 0x12, 0x80, 0x2c, 0x52, 0x15, 0xe2, - 0x51, 0x37, 0xcf, 0xdd, 0x13, 0x8c, 0x99, 0x39, 0x0e, 0xfb, 0xce, 0xb7, 0x52, 0x4e, - 0x84, 0x7c, 0x36, 0xb4, 0x3f, 0x3e, 0xde, 0x32, 0xf2, 0x3b, 0x39, 0x81, 0xf6, 0xd3, - 0xc3, 0x2b, 0x17, 0xbb, 0xbe, 0x65, 0xf2, 0xfd, 0x01, 0xab, 0xdd, 0x99, 0x87, 0xf1, - 0xb8, 0x88, 0xeb, 0xef, 0x41, 0xef, 0x45, 0x55, 0xc9, 0xfb, 0x0c, 0x8a, 0xee, 0x9b, - 0x6d, 0xd0, 0x85, 0xb9, 0xfb, 0xc7, 0x4f, 0xe4, 0x6a, 0x1e, 0x36, 0x3d, 0x68, 0x32, - 0xb5, 0x08, 0x20, 0x0e, 0x50, 0x0d, 0xa6, 0x95, 0x13, 0xb7, 0x9e, 0x81, 0xf7, 0x33, - 0xb6, 0x6c, 0x3f, 0x24, 0x3a, 0x28, 0x5b, 0xf8, 0x6f, 0xfe, 0xef, 0x4f, 0xfd, 0x1c, - 0xac, 0xa7, 0x83, 0x07, 0x26, 0x63, 0xbf, 0x9b, 0x48, 0x7f, 0xbc, 0x3e, 0x7f, 0x5a, - 0xd2, 0xf7, 0xac, 0xbf, 0x2b, 0x6e, 0x00, 0x8e, 0x3e, 0x4d, 0x6f, 0x31, 0xe1, 0x14, - 0x75, 0xe1, 0x96, 0x98, 0x9d, 0xb9, 0x62, 0x8a, 0x5d, 0x56, 0x39, 0x7c, 0x9a, 0x04, - 0x2a, 0xab, 0x55, 0xe1, 0xec, 0xc4, 0x92, 0xfe, 0x94, 0x27, 0xd4, 0x90, 0xf2, 0x73, - 0xb6, 0x01, 0xd6, 0x51, 0x05, 0x56, 0x82, 0xd3, 0x5b, 0x30, 0x75, 0xfa, 0xda, 0x85, - 0x25, 0x84, 0x48, 0x14, 0x95, 0x7f, 0xfc, 0x9b, 0xc7, 0xfb, 0x39, 0x39, 0x73, 0x7b, - 0x01, 0x50, 0x2e, 0x0b, 0x6f, 0x1f, 0x9b, 0x88, 0xf2, 0x71, 0x54, 0x80, 0xae, 0x42, - 0x2e, 0x9b, 0xb7, 0xb7, 0x6e, 0x5d, 0x22, 0xde, 0x0d, 0x3d, 0x7a, 0xea, 0x58, 0x10, - 0x01, 0xdc, 0xf4, 0x6a, 0x62, 0x2f, 0x08, 0x03, 0x10, 0xbe, 0x50, 0xdf, 0x07, 0x75, - 0x21, 0x92, 0xd4, 0xe4, 0x1a, 0xc5, 0x18, 0xe4, 0x24, 0x1e, 0x06, 0x67, 0x76, 0xa8, - 0xea, 0xec, 0xc7, 0x42, 0xfd, 0x2c, 0x1b, 0xf0, 0x6f, 0xc5, 0x8b, 0xd2, 0x8d, 0x1d, - 0x6c, 0x60, 0x1f, 0x91, 0x5d, 0x75, 0x2e, 0x7c, 0xc3, 0xd9, 0x76, 0x3c, 0x8b, 0x9e, - 0xec, 0x14, 0x2c, 0x84, 0x81, 0xf9, 0xc5, 0x23, 0x59, 0xbf, 0xbf, 0x51, 0x24, 0x36, - 0x67, 0x84, 0xe1, 0x71, 0xd7, 0xa4, 0xaa, 0x01, 0x5e, 0x85, 0x56, 0x47, 0x4a, 0x6d, - 0x0f, 0xee, 0x69, 0xb0, 0xd5, 0x3e, 0xe7, 0xf4, 0xed, 0xf5, 0xea, 0x59, 0xfa, 0x55, - 0x97, 0xf4, 0x8d, 0xd6, 0xaa, 0x88, 0x51, 0x84, 0x29, 0xac, 0x8c, 0x18, 0xc4, 0x73, - 0x8d, 0xb8, 0x01, 0x09, 0xa5, 0xe4, 0xbc, 0x81, 0xbb, 0x84, 0xb3, 0x7d, 0x9b, 0x2a, - 0xd4, 0xb1, 0xd2, 0x6b, 0x36, 0x3d, 0x16, 0x60, 0x72, 0xf0, 0x8c, 0x56, 0x70, 0x62, - 0x27, 0xa9, 0xf8, 0x32, 0x97, 0x03, 0x70, 0x12, 0xd1, 0xf6, 0xda, 0x24, 0xa8, 0x69, - 0xeb, 0x32, 0x97, 0xbc, 0xbc, 0xcc, 0x8d, 0x7d, 0xed, 0x03, 0x0a, 0x3d, 0x60, 0xdf, - 0x88, 0x82, 0xe0, 0x62, 0x9e, 0x36, 0x14, 0x3c, 0x09, 0xca, 0x05, 0x21, 0x43, 0xcb, - 0x56, 0x62, 0x93, 0x8f, 0xa9, 0xf1, 0x15, 0xdd, 0xc0, 0x96, 0x65, 0x4c, 0x0b, 0x40, - 0x59, 0x4c, 0xba, 0x19, 0xee, 0xd4, 0x99, 0x53, 0x2b, 0x70, 0x8a, 0xde, 0xbe, 0x47, - 0x72, 0x6a, 0x83, 0xaf, 0x46, 0x3c, 0x80, 0xba, 0x2a, 0x1f, 0xe0, 0x71, 0xe1, 0x66, - 0xc4, 0x4d, 0x70, 0xdd, 0xbb, 0xba, 0x67, 0x06, 0xa1, 0xdc, 0x43, 0x27, 0x26, 0xfe, - 0x0f, 0xdb, 0xc6, 0x28, 0x21, 0xb5, 0x04, 0xea, 0x11, 0x66, 0xda, 0x48, 0xa8, 0x1b, - 0x63, 0x5e, 0x37, 0x63, 0x33, 0xd9, 0xbe, 0xfe, 0xc4, 0x93, 0xa0, 0x7d, 0xf4, 0x7b, - 0xba, 0x0a, 0x2e, 0x2f, 0x65, 0xe7, + 0x3f, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, + 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, + 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, + 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0x3c, 0x1b, 0x65, 0x1a, + 0x9d, 0xe1, 0xb5, 0xc1, 0xa6, 0xe0, 0x48, 0x2f, 0xae, 0x8f, 0x98, 0x6a, 0xb5, 0x9f, + 0xa7, 0xcd, 0x43, 0x98, 0x99, 0x6e, 0x2b, 0xc0, 0x3a, 0xdc, 0xa9, 0x90, 0x32, 0x3b, + 0xaa, 0xbd, 0xda, 0xae, 0x40, 0xb0, 0x56, 0xb7, 0xac, 0x17, 0xf8, 0x20, 0xd1, 0x1c, + 0x0d, 0xec, 0xba, 0x14, 0xf2, 0x57, 0xa6, 0xcf, 0x09, 0x18, 0x19, 0x8f, 0x38, 0x9c, + 0xdb, 0x29, 0x55, 0x77, 0x25, 0x96, 0x92, 0x7c, 0xbf, 0x55, 0x88, 0x56, 0x13, 0x35, + 0xe7, 0xd6, 0x2e, 0x6a, 0x8a, 0xf7, 0xbc, 0x33, 0xb9, 0x9a, 0x55, 0xaf, 0xa1, 0xb7, + 0xef, 0x20, 0xeb, 0x4e, 0xd6, 0xde, 0x89, 0x69, 0xd2, 0x9f, 0x04, 0x21, 0xcd, 0x4d, + 0x99, 0x06, 0x66, 0xfd, 0xcf, 0x1e, 0xbd, 0x09, 0x06, 0x57, 0x02, 0x13, 0x4d, 0x31, + 0xc3, 0x29, 0x26, 0xa3, 0x8b, 0x6b, 0x6b, 0x48, 0xfd, 0xc9, 0xb3, 0xc7, 0x64, 0xc3, + 0xcd, 0x95, 0xb9, 0x72, 0xe7, 0x68, 0xeb, 0xd8, 0xaa, 0xe9, 0x0d, 0x6a, 0x4a, 0x98, + 0xb2, 0xd9, 0x2f, 0xd9, 0xdf, 0xa2, 0xa2, 0x99, 0xd0, 0x60, 0xe8, 0x5e, 0xf5, 0x68, + 0x3f, 0x51, 0xd0, 0x51, 0x4a, 0x6e, 0xba, 0x72, 0x57, 0x3f, 0x7b, 0xae, 0x84, 0xa2, + 0xfd, 0x92, 0xbe, 0x64, 0x24, 0x1c, 0x27, 0xa6, 0xe5, 0xce, 0xac, 0xbf, 0x37, 0xb2, + 0xd9, 0xa9, 0x75, 0xdf, 0x7a, 0xee, 0xbb, 0xa1, 0x4d, 0x8c, 0x81, 0x15, 0x8e, 0xcf, + 0x5a, 0x0a, 0x25, 0xe1, 0x2f, 0x98, 0x5d, 0x08, 0xfb, 0xb4, 0xa1, 0xc1, 0x3f, 0x76, + 0x1f, 0x3f, 0xfe, 0xe8, 0xd5, 0x38, 0xe3, 0x93, 0xf3, 0x58, 0x0b, 0x73, 0x82, 0xcd, + 0x0b, 0xf5, 0x17, 0xce, 0x78, 0x87, 0x1c, 0x19, 0xac, 0xf8, 0xca, 0x06, 0x5d, 0x7c, + 0x83, 0x87, 0xce, 0xcd, 0x0d, 0x37, 0xae, 0x21, 0x7f, 0x44, 0x06, 0x94, 0x77, 0x2a, + 0xbd, 0x4b, 0x36, 0x55, 0x56, 0x85, 0x4b, 0xaa, 0x8b, 0xcc, 0xa9, 0xc4, 0xfe, 0xf7, + 0x18, 0x99, 0x12, 0xf9, 0x8a, 0x25, 0x27, 0x68, 0x92, 0x76, 0xa4, 0x00, 0x8c, 0x83, + 0x8f, 0xe7, 0x4f, 0x7c, 0x2b, 0x75, 0x9f, 0xc2, 0xab, 0x7a, 0xfe, 0x37, 0x82, 0x80, + 0x6e, 0x31, 0xb1, 0xc5, 0x30, 0xcc, 0x46, 0x20, 0x3b, 0xb3, 0xa5, 0x66, 0xca, 0xf4, + 0xd1, 0x5b, 0x99, 0x40, 0xb4, 0x3f, 0x33, 0xa8, 0x6a, 0x65, 0xd4, 0x9d, 0xa8, 0xb6, + 0x78, 0x7d, 0xe0, 0x96, 0x38, 0xb4, 0x81, 0xf3, 0xa8, 0x10, 0x8a, 0x96, 0x9e, 0xca, + 0xdf, 0x90, 0x98, 0xbf, 0xf2, 0x14, 0x0c, 0x4b, 0x42, 0xe2, 0xb0, 0xfb, 0x10, 0xb9, + 0x02, 0x89, 0xb0, 0xc6, 0xdb, 0x8b, 0xc0, 0x85, 0xe8, 0xaf, 0xe9, 0x5d, 0xd3, 0x6a, + 0x45, 0x36, 0xea, 0xd7, 0xe9, 0x5c, 0x99, 0x66, 0x2c, 0xd9, 0x28, 0xc2, 0x2c, 0x3e, + 0xbf, 0x39, 0x79, 0x15, 0x78, 0xbc, 0x66, 0xfe, 0xa3, 0x01, 0x4d, 0x22, 0x92, 0x94, + 0x30, 0x83, 0xe7, 0x46, 0x81, 0x24, 0x52, 0xb0, 0x0b, 0xc2, 0xf3, 0xe4, 0x7c, 0x49, + 0x47, 0x46, 0xce, 0xd5, 0x57, 0xb1, 0x3a, 0xe3, 0x03, 0x0d, 0x8a, 0x95, 0x78, 0x10, + 0x2b, 0xba, 0xd2, 0xfc, 0x3b, 0x84, 0x5f, 0x31, 0xae, 0x16, 0xf8, 0xd8, 0x0b, 0x77, + 0xf8, 0x43, 0x15, 0x84, 0xa3, 0x7e, 0x8f, 0x30, 0xb0, 0xb9, 0x5c, 0xc4, 0x55, 0x5a, + 0xbc, 0x05, 0x3a, 0x0b, 0x4f, 0xf9, 0x13, 0xb0, 0x03, 0x69, 0xf1, 0x74, 0x7b, 0x1f, + 0x1c, 0x0a, 0xc8, 0x75, 0x4f, 0x01, 0x7e, 0x99, 0x47, 0xca, 0x63, 0x25, 0x5b, 0x3c, + 0x23, 0xf4, 0x56, 0xe2, 0x3f, 0x96, 0x76, 0x13, 0x99, 0x60, 0x1f, 0xd8, 0xda, 0xdb, + 0x5e, 0x3f, 0x90, 0xab, 0x1b, 0x20, 0x13, 0x81, 0x80, 0xed, 0x69, 0x73, 0x22, 0x39, + 0xc8, 0xc2, 0x15, 0xd9, 0xcc, 0x8a, 0xc8, 0x05, 0x9b, 0xde, 0x81, 0x63, 0x27, 0xd2, + 0x20, 0xb9, 0xa8, 0xec, 0xba, 0x5d, ], ock: [ - 0xec, 0xa3, 0x70, 0x7a, 0x74, 0x5d, 0x5d, 0x58, 0x65, 0x86, 0xb2, 0x35, 0xf2, 0x92, - 0xad, 0x20, 0x48, 0x93, 0x14, 0xc4, 0x58, 0x80, 0xd9, 0x83, 0x2b, 0x7f, 0x47, 0xee, - 0xbb, 0xd4, 0x5c, 0xfe, + 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, + 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, + 0x50, 0xc5, 0xcf, 0x2d, ], op: [ 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, - 0x03, 0x8e, 0x3d, 0xb3, 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, - 0x40, 0xaf, 0x89, 0x3e, 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, - 0x6b, 0x5e, 0xd1, 0xf6, 0xbf, 0x62, 0xbe, 0x3c, + 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, + 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, + 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, ], c_out: [ - 0xd0, 0x65, 0x9a, 0x03, 0xc5, 0x3e, 0x15, 0xdc, 0x11, 0x01, 0xa6, 0x6e, 0xa8, 0x0d, - 0xf4, 0x14, 0x4d, 0x5e, 0xe0, 0x1c, 0x3d, 0xbf, 0x20, 0x2c, 0xe6, 0x08, 0x7e, 0x96, - 0xa8, 0x5a, 0xe1, 0x39, 0xdd, 0x46, 0xfc, 0x82, 0xa1, 0xc3, 0x7d, 0x06, 0x05, 0xf8, - 0x49, 0x98, 0x53, 0x13, 0x16, 0xf1, 0xf0, 0xcb, 0xc0, 0x4e, 0xa2, 0x0a, 0xa4, 0x04, - 0xb3, 0xd5, 0xb0, 0x42, 0x96, 0x01, 0x49, 0x81, 0x6d, 0x9b, 0x8f, 0x06, 0x2a, 0xfc, - 0xc1, 0x93, 0x89, 0x43, 0x82, 0x7a, 0x1b, 0x43, 0xfc, 0xbd, + 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, + 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, + 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, + 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, + 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, + 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, ], }, TestVector { @@ -1142,34 +1142,34 @@ pub(crate) fn test_vectors() -> Vec { 0xda, 0x6b, 0x15, 0x14, ], nf_old: [ - 0xe5, 0xd0, 0x8c, 0x40, 0x26, 0x3e, 0x4a, 0x2a, 0x56, 0x96, 0xda, 0x21, 0x0d, 0x8e, - 0x9a, 0x77, 0xf0, 0xaf, 0xc4, 0xc6, 0x8a, 0x6d, 0xda, 0x38, 0xe2, 0x85, 0xf4, 0xe3, - 0xef, 0x13, 0xb8, 0x17, + 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, + 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, + 0x21, 0x38, 0xab, 0x29, ], cmx: [ - 0xad, 0xc2, 0x44, 0x3a, 0xf9, 0x57, 0x67, 0x47, 0xca, 0x4f, 0x10, 0x4b, 0x1f, 0x5a, - 0x7a, 0xdc, 0x80, 0x5a, 0xc5, 0x5a, 0xcc, 0x56, 0x33, 0xa0, 0xb3, 0xc2, 0xdc, 0x7a, - 0xad, 0xff, 0x21, 0x26, + 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, + 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, + 0x97, 0xf8, 0x9c, 0x20, ], esk: [ - 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, 0x82, 0x35, 0x16, 0x58, - 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, 0xb0, 0x52, 0xd5, 0xb4, - 0x20, 0x41, 0xd8, 0x1c, + 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, + 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, + 0xcc, 0xd5, 0x4e, 0x3a, ], ephemeral_key: [ - 0x00, 0x5d, 0x31, 0x5b, 0xd1, 0x80, 0xa2, 0x94, 0x0b, 0xd7, 0xfb, 0x34, 0xa7, 0x0e, - 0x90, 0xe8, 0x32, 0x6c, 0xb1, 0x34, 0x30, 0x66, 0x05, 0x46, 0x53, 0xd2, 0x64, 0x4d, - 0x20, 0x45, 0xe3, 0x0f, + 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, + 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, + 0xd3, 0xbf, 0x0e, 0x8f, ], shared_secret: [ - 0x8e, 0x59, 0x0d, 0x06, 0x3f, 0x7e, 0xc3, 0x8e, 0xb2, 0x00, 0x84, 0x70, 0xf9, 0xbb, - 0x42, 0x29, 0x04, 0xfc, 0x0b, 0xaf, 0x97, 0x80, 0xf8, 0xfd, 0x1f, 0x54, 0x22, 0xea, - 0x30, 0x8c, 0x47, 0xba, + 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, + 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, + 0x61, 0xfd, 0xaf, 0xb5, ], k_enc: [ - 0xeb, 0xb2, 0xff, 0x9b, 0x1f, 0x29, 0x0d, 0xa5, 0x63, 0x27, 0xa9, 0x67, 0x71, 0xb2, - 0x5f, 0x71, 0x29, 0xff, 0x10, 0x2e, 0xe6, 0xd2, 0xb2, 0x0d, 0xa0, 0x9a, 0x06, 0x25, - 0xf8, 0xbb, 0x26, 0x07, + 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, + 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, + 0x18, 0x06, 0x9e, 0x99, ], p_enc: [ 0x02, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, @@ -1215,68 +1215,68 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0x1e, 0x4e, 0x6f, ], c_enc: [ - 0x96, 0x3b, 0xe3, 0x6e, 0xdc, 0xa4, 0x8b, 0x7c, 0x4a, 0x1c, 0xd6, 0xa1, 0x37, 0x2e, - 0x84, 0xc0, 0x54, 0x54, 0x83, 0x4c, 0x5e, 0xe1, 0x92, 0x5e, 0xed, 0xeb, 0x48, 0xda, - 0x16, 0x77, 0x79, 0xe3, 0x99, 0x83, 0x58, 0xcb, 0x92, 0x7a, 0x0a, 0x0b, 0x36, 0x9c, - 0x85, 0xee, 0xb3, 0x30, 0xf7, 0x00, 0x5c, 0x26, 0x9d, 0x0b, 0xe4, 0xf2, 0x38, 0x09, - 0x57, 0xb1, 0x62, 0x97, 0x7c, 0xae, 0x7a, 0x7b, 0x1d, 0x0b, 0xe5, 0xd0, 0xb7, 0x03, - 0xd3, 0x92, 0xac, 0xae, 0xd2, 0x4f, 0x52, 0x5b, 0x83, 0xcf, 0xdd, 0x7f, 0x35, 0xc1, - 0xf1, 0x74, 0xbf, 0x06, 0x6b, 0x7a, 0xfd, 0xb7, 0x45, 0xed, 0xbe, 0xdc, 0x0b, 0x46, - 0xa5, 0x91, 0x36, 0x21, 0x47, 0x61, 0x9d, 0x6b, 0xd3, 0xf3, 0xce, 0x6b, 0x45, 0x23, - 0xf0, 0x64, 0x9a, 0x7c, 0x65, 0x32, 0x2d, 0x05, 0xfa, 0xe2, 0x22, 0x70, 0x1a, 0x8c, - 0xd6, 0xca, 0xbf, 0x8d, 0xc3, 0x2f, 0x05, 0x5f, 0xeb, 0x14, 0x1e, 0x55, 0x6d, 0xdf, - 0xb1, 0x98, 0x30, 0xb7, 0x20, 0x4c, 0x30, 0x98, 0x4e, 0xdd, 0xf4, 0x34, 0xec, 0xc5, - 0xf0, 0xea, 0x82, 0x5c, 0xf8, 0xd9, 0xd5, 0x03, 0x8f, 0x28, 0xe2, 0x3e, 0xf3, 0x6b, - 0xa9, 0x38, 0x52, 0xe5, 0x8e, 0x85, 0xf8, 0x90, 0xb1, 0x77, 0x5c, 0x6d, 0x4c, 0x13, - 0x5b, 0xef, 0x0e, 0x2a, 0x19, 0x33, 0x02, 0xd9, 0x0a, 0x80, 0x4c, 0x85, 0x31, 0x25, - 0xaa, 0x5b, 0x11, 0x6f, 0x8c, 0x58, 0x0e, 0xb6, 0x54, 0xfe, 0x35, 0xe6, 0x73, 0x79, - 0x9e, 0x93, 0xcf, 0x58, 0xfe, 0x1e, 0x70, 0xcd, 0xe1, 0x19, 0xab, 0x58, 0x6c, 0x12, - 0xc4, 0x95, 0x75, 0xe6, 0x1a, 0xc4, 0xb7, 0x71, 0xfa, 0x8e, 0xbf, 0x76, 0xca, 0x95, - 0xd6, 0x51, 0xa4, 0xba, 0x87, 0x3b, 0x24, 0xcf, 0x97, 0xff, 0x75, 0x5b, 0xc7, 0x49, - 0xf4, 0x09, 0x6d, 0x2d, 0xa1, 0x5c, 0xf8, 0x30, 0x36, 0xcc, 0x22, 0x0f, 0x0a, 0x68, - 0x93, 0x43, 0x21, 0xc9, 0xae, 0x33, 0x4e, 0x2d, 0x99, 0xa9, 0x95, 0xe9, 0x29, 0x04, - 0xc1, 0x45, 0x23, 0x33, 0x19, 0x00, 0xcb, 0xca, 0x20, 0x4a, 0xdc, 0xb6, 0x93, 0x9d, - 0xc1, 0x71, 0x87, 0x53, 0x53, 0xa1, 0x1e, 0x12, 0xba, 0xcb, 0x2a, 0xab, 0x0f, 0x57, - 0x17, 0x9f, 0x1b, 0x67, 0xea, 0xcc, 0x7e, 0x7b, 0x6c, 0x5c, 0xc8, 0xa3, 0x78, 0x64, - 0x9b, 0x62, 0xb8, 0x52, 0xfa, 0x47, 0x6f, 0x93, 0x37, 0x88, 0x59, 0xd0, 0xd9, 0xa3, - 0x03, 0x3d, 0xa1, 0x31, 0x28, 0x17, 0x57, 0xad, 0x98, 0x5c, 0x86, 0xfe, 0x03, 0x7a, - 0x4e, 0xdd, 0x0a, 0x4a, 0x49, 0xee, 0x5c, 0x4f, 0x48, 0x15, 0xf0, 0x14, 0x73, 0xb9, - 0x60, 0xa1, 0x8a, 0x3b, 0x7f, 0x75, 0x07, 0xee, 0x3d, 0x8b, 0x39, 0x5a, 0x76, 0x68, - 0x40, 0x95, 0x5b, 0xaa, 0xdd, 0x0a, 0xbb, 0xf4, 0xf5, 0x91, 0x4e, 0x92, 0x10, 0xf5, - 0x9e, 0x4c, 0xd1, 0x3c, 0x82, 0xe0, 0xac, 0xf8, 0x79, 0x51, 0x78, 0x02, 0x91, 0xd0, - 0xa9, 0xa7, 0x0f, 0x6b, 0x4f, 0xf5, 0x0d, 0x81, 0x0d, 0x50, 0x90, 0x20, 0x45, 0x30, - 0xad, 0x69, 0x44, 0xb1, 0x3d, 0x23, 0x83, 0xab, 0xca, 0x42, 0x0c, 0xb6, 0xd9, 0xfc, - 0xd8, 0xfd, 0xcb, 0xe9, 0xb3, 0xb5, 0xf4, 0x2f, 0x0a, 0xf5, 0xdf, 0x36, 0x37, 0x8c, - 0xe7, 0x3d, 0xc9, 0x06, 0x16, 0x7d, 0xd4, 0xb3, 0x80, 0x41, 0x8f, 0x17, 0xe4, 0x50, - 0x61, 0x18, 0x57, 0x23, 0xda, 0xbb, 0x6f, 0xfd, 0xbb, 0xd5, 0xa4, 0x18, 0xc3, 0xc6, - 0xfd, 0x33, 0x70, 0x34, 0x09, 0x94, 0x27, 0x7b, 0x88, 0x8e, 0xe4, 0x9b, 0x08, 0x91, - 0xbb, 0xb9, 0x4b, 0x6b, 0x8b, 0x06, 0x5f, 0xd1, 0x92, 0x00, 0xdc, 0x3a, 0x68, 0x1c, - 0xa5, 0xff, 0x2a, 0x98, 0x8f, 0xa6, 0x6d, 0x02, 0x9d, 0xdd, 0xf9, 0xb0, 0x3a, 0x5e, - 0x6c, 0x6e, 0x99, 0xb6, 0x35, 0x41, 0x15, 0x6a, 0x09, 0x51, 0xd9, 0x08, 0x7d, 0xd8, - 0x83, 0xd5, 0x13, 0x9e, 0xe6, 0x7a, 0x8c, 0xe5, 0xdd, 0x6e, 0xf1, 0x4c, 0x9a, 0x10, - 0xdb, 0x81, 0x8b, 0x93, 0x69, 0x02, 0xc7, 0x99, 0x93, 0x90, 0xf9, 0x72, 0xba, 0xfa, - 0x5a, 0x57, 0x2f, 0xc8, 0x73, 0x42, 0xe2, 0xc5, 0x1c, 0xeb, 0x80, 0x30, 0xe0, 0x6b, - 0x72, 0x40, 0x95, 0xf9, 0x8d, 0x7b, + 0xbe, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, + 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, + 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, + 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0xcb, 0x22, 0x81, 0x4a, + 0x04, 0x69, 0x39, 0xd2, 0xff, 0xf9, 0x2b, 0x46, 0x62, 0x76, 0x2d, 0x4f, 0x21, 0xc0, + 0x78, 0x42, 0x74, 0x72, 0xb9, 0x18, 0x10, 0x10, 0x55, 0x56, 0xf4, 0xde, 0x0a, 0x27, + 0xe7, 0x70, 0x08, 0x47, 0x72, 0xcb, 0xfe, 0xbf, 0x87, 0xdb, 0x33, 0x14, 0xab, 0x70, + 0xf2, 0x6d, 0x11, 0xea, 0x5d, 0xe2, 0x67, 0xc3, 0xa9, 0xa8, 0xf4, 0x6b, 0xad, 0x13, + 0xc7, 0x36, 0x26, 0x10, 0xbd, 0xba, 0x81, 0x02, 0xd4, 0xb7, 0x26, 0xef, 0x26, 0xec, + 0x79, 0x4a, 0x15, 0x66, 0x57, 0x1b, 0xfd, 0xc1, 0x02, 0x47, 0x7d, 0xa5, 0xb4, 0x9b, + 0xbf, 0x9f, 0xe4, 0xb1, 0xa4, 0x4e, 0xd0, 0xb3, 0xbc, 0xed, 0x99, 0xba, 0x81, 0x9a, + 0x4f, 0x30, 0x22, 0x65, 0x49, 0x44, 0x5b, 0xc6, 0x1c, 0xff, 0x5c, 0x33, 0x16, 0x33, + 0x5f, 0x6b, 0xd4, 0xa9, 0xa4, 0x24, 0xc9, 0x4a, 0xe0, 0xb5, 0xcb, 0xe4, 0x8a, 0xfb, + 0x2b, 0x94, 0xd0, 0xc7, 0xe4, 0x4e, 0x32, 0x30, 0x95, 0xa7, 0x2e, 0x42, 0x64, 0xe9, + 0x1c, 0x48, 0x94, 0xb9, 0xe8, 0x45, 0xaf, 0x32, 0x35, 0x02, 0xda, 0xe8, 0xc1, 0x86, + 0x78, 0xa4, 0xf7, 0x40, 0xe5, 0xa6, 0x3a, 0x4c, 0x70, 0x29, 0x92, 0xfa, 0xcd, 0xd3, + 0x57, 0x35, 0xb1, 0xd1, 0x34, 0x8b, 0x91, 0x9c, 0x70, 0x0c, 0x42, 0xd3, 0x30, 0xd3, + 0x86, 0xaf, 0xb8, 0x73, 0xfa, 0xba, 0xd8, 0xcb, 0x32, 0x18, 0x15, 0x1b, 0x40, 0x18, + 0x01, 0xe3, 0x69, 0x34, 0x4f, 0xf2, 0x0a, 0xaa, 0x66, 0x73, 0x47, 0x4f, 0x4b, 0xfc, + 0x98, 0xd0, 0x7e, 0x36, 0x7b, 0xc4, 0x2e, 0xf1, 0xa0, 0x4f, 0xa1, 0xbc, 0x12, 0x52, + 0x18, 0x8d, 0xd9, 0xd3, 0xe0, 0x00, 0xe3, 0xf5, 0xe9, 0xdf, 0xc9, 0xe1, 0x3e, 0xe9, + 0xdb, 0x55, 0x04, 0x0d, 0x17, 0x22, 0x7d, 0xa4, 0x4a, 0x3e, 0x08, 0xfd, 0x5e, 0xc8, + 0x58, 0xc4, 0x9c, 0x2e, 0x6a, 0x71, 0x1f, 0x8e, 0x68, 0xd0, 0xa1, 0xdf, 0x88, 0xef, + 0x09, 0x40, 0xf7, 0x2e, 0xd7, 0x3e, 0xf4, 0x9e, 0x8a, 0x45, 0xae, 0x2e, 0x5e, 0x1b, + 0xf1, 0x37, 0xba, 0x58, 0xcf, 0xb9, 0x25, 0x79, 0xab, 0xb2, 0xa4, 0x93, 0x13, 0xa2, + 0xff, 0x3d, 0xb6, 0x16, 0x93, 0xd2, 0xb7, 0x58, 0xaf, 0x20, 0x47, 0x2a, 0xc6, 0x40, + 0x6b, 0xa3, 0x55, 0xb4, 0x8c, 0xee, 0x22, 0xe7, 0x0f, 0xb8, 0xf9, 0xd4, 0x8e, 0xa3, + 0x93, 0x4b, 0x62, 0x24, 0xac, 0xe2, 0x69, 0xb9, 0xef, 0x54, 0x6d, 0xbf, 0xc5, 0x2a, + 0xbe, 0xcf, 0xac, 0x59, 0x40, 0xf0, 0x40, 0xbd, 0x21, 0xe9, 0x0e, 0xfa, 0x82, 0x75, + 0x56, 0x1a, 0x88, 0xbc, 0x18, 0xe2, 0x6b, 0x98, 0x8d, 0x11, 0x79, 0xb7, 0xa2, 0xc3, + 0xaf, 0xd8, 0x6e, 0xf2, 0xa0, 0x90, 0x62, 0x52, 0x23, 0x23, 0x4b, 0x39, 0xc9, 0xe2, + 0x06, 0x8d, 0x94, 0x5d, 0xd7, 0x76, 0x3b, 0x01, 0x0c, 0x28, 0xc8, 0x9b, 0x72, 0xe2, + 0x55, 0x13, 0xb3, 0x9c, 0x3c, 0xe1, 0x17, 0x73, 0x42, 0x8a, 0xd3, 0x44, 0xe1, 0xd5, + 0xd5, 0x1b, 0x92, 0x00, 0x14, 0xf9, 0x17, 0x06, 0xff, 0xae, 0x3d, 0x86, 0x36, 0x14, + 0x77, 0xfd, 0x5d, 0xe0, 0x13, 0x42, 0x2c, 0x06, 0xa3, 0x32, 0xe3, 0x45, 0x79, 0x75, + 0xcf, 0x9b, 0xe9, 0xf9, 0xab, 0x3a, 0x06, 0x87, 0x2e, 0xf0, 0x71, 0x7d, 0x39, 0x08, + 0xbd, 0xeb, 0xf8, 0x41, 0x8c, 0xe5, 0x57, 0xd5, 0x2d, 0x51, 0xa2, 0x50, 0xc0, 0x8c, + 0x5b, 0x79, 0x3a, 0xd4, 0xbc, 0x0f, 0x16, 0xc6, 0x27, 0x89, 0xfe, 0xa2, 0xca, 0xb3, + 0x9c, 0xcc, 0xa4, 0x07, 0xee, 0x9e, 0x47, 0xf5, 0x6d, 0x20, 0xa7, 0x41, 0x91, 0x2c, + 0x6b, 0xad, 0xdb, 0xd7, 0xfa, 0x7b, 0x97, 0xe5, 0x46, 0x33, 0x61, 0x28, 0x74, 0x5a, + 0xe7, 0xd7, 0x30, 0xa5, 0x5a, 0x6a, 0xc7, 0xb8, 0xfc, 0xbd, 0x72, 0xce, 0x78, 0x95, + 0x9c, 0x7a, 0x79, 0x75, 0x21, 0x2c, ], ock: [ - 0x5b, 0x5b, 0x20, 0xfc, 0x46, 0xba, 0x14, 0xbd, 0x18, 0x43, 0xb6, 0xc7, 0x7e, 0xc3, - 0xf4, 0x55, 0xb7, 0x65, 0xb4, 0xd1, 0x2d, 0xb6, 0x52, 0xeb, 0x34, 0x20, 0x0c, 0x41, - 0x48, 0x88, 0x1f, 0xfc, + 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, + 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, + 0x8e, 0x29, 0x42, 0xa3, ], op: [ 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, - 0x67, 0xa8, 0x60, 0x9e, 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, - 0x82, 0x35, 0x16, 0x58, 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, - 0xb0, 0x52, 0xd5, 0xb4, 0x20, 0x41, 0xd8, 0x1c, + 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, + 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, + 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, ], c_out: [ - 0xe0, 0x1b, 0x5c, 0x1e, 0x01, 0x90, 0x0f, 0xf7, 0x9b, 0xf7, 0x27, 0xf5, 0x37, 0xc4, - 0xac, 0x36, 0xf8, 0x06, 0x7a, 0x0c, 0xc5, 0xc8, 0xe9, 0xc8, 0x20, 0x44, 0x28, 0x43, - 0x69, 0x35, 0x30, 0x91, 0x8a, 0xea, 0x67, 0x2c, 0x4c, 0xd8, 0xfa, 0x3f, 0x6f, 0x2c, - 0xb6, 0x8b, 0x87, 0x17, 0x22, 0xe7, 0x78, 0xf6, 0xe2, 0x5e, 0x78, 0xae, 0x00, 0xa8, - 0x43, 0x28, 0xc4, 0xc2, 0xbf, 0x1c, 0x79, 0xb2, 0xc9, 0xd8, 0x69, 0x72, 0x60, 0xcd, - 0x44, 0x7e, 0x2e, 0xff, 0x31, 0x5d, 0x74, 0xb5, 0xb1, 0xfd, + 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, + 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, + 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, + 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, + 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, + 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, ], }, TestVector { @@ -1351,34 +1351,34 @@ pub(crate) fn test_vectors() -> Vec { 0x88, 0xff, 0xee, 0x2f, ], nf_old: [ - 0xe9, 0x16, 0x93, 0xc3, 0x7d, 0x04, 0x37, 0x5e, 0x67, 0xc5, 0x71, 0x5a, 0x39, 0xc9, - 0x79, 0x4a, 0x4e, 0xcd, 0x08, 0x38, 0xe2, 0x35, 0x1f, 0xd7, 0xcd, 0x93, 0xa1, 0x55, - 0x7f, 0x01, 0x02, 0x3e, + 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, + 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, + 0x92, 0xd7, 0xa0, 0x24, ], cmx: [ - 0xcc, 0x29, 0x41, 0xe0, 0xf6, 0x38, 0x25, 0x7f, 0xb6, 0x51, 0x6a, 0x27, 0xc3, 0x0e, - 0xaa, 0xe0, 0xb4, 0x6d, 0x2f, 0xf0, 0x6a, 0x73, 0x50, 0x70, 0x41, 0x74, 0x6c, 0xdc, - 0x23, 0x07, 0x61, 0x25, + 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, + 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, + 0x67, 0xd4, 0x93, 0x0b, ], esk: [ - 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, 0xbf, 0xb7, 0x8a, 0xec, - 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, 0x77, 0xc9, 0x46, 0xe9, - 0xcd, 0x7a, 0x24, 0x23, + 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, + 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, + 0xc7, 0xda, 0x74, 0x36, ], ephemeral_key: [ - 0xad, 0xa7, 0x60, 0x27, 0xdc, 0xae, 0xb5, 0xf1, 0x58, 0xac, 0x6c, 0x5c, 0x6d, 0x7f, - 0x05, 0x31, 0x8f, 0xec, 0x26, 0xd5, 0xc7, 0x94, 0xf2, 0xe9, 0x00, 0xcb, 0x96, 0x29, - 0x92, 0x49, 0xe0, 0xb5, + 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, + 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, + 0x23, 0x1a, 0x61, 0x34, ], shared_secret: [ - 0xc2, 0x5c, 0xf1, 0xd6, 0x53, 0x2e, 0x06, 0xcb, 0x8b, 0x15, 0x22, 0x14, 0x76, 0x6e, - 0xee, 0xd7, 0x5a, 0x17, 0x8c, 0x82, 0x2a, 0x11, 0x51, 0xf6, 0x9e, 0x92, 0xe9, 0xcf, - 0xfa, 0x47, 0xcb, 0x19, + 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, + 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, + 0x3f, 0x5c, 0xc5, 0x37, ], k_enc: [ - 0xd4, 0xef, 0x89, 0xc4, 0x64, 0xbe, 0x8f, 0x42, 0xf6, 0xb7, 0xf2, 0x6d, 0x89, 0x37, - 0x8b, 0x73, 0xa3, 0x55, 0xa4, 0xfe, 0x24, 0x6c, 0x2e, 0xc8, 0xe8, 0x14, 0x6b, 0xef, - 0x7d, 0xdd, 0x14, 0x19, + 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, + 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, + 0xbe, 0x25, 0xe9, 0x8d, ], p_enc: [ 0x02, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, @@ -1424,68 +1424,68 @@ pub(crate) fn test_vectors() -> Vec { 0x1a, 0x81, 0xa3, 0x59, ], c_enc: [ - 0xea, 0x86, 0x7e, 0x07, 0xac, 0xb7, 0xfa, 0x03, 0xe7, 0x36, 0xce, 0xdd, 0xed, 0x82, - 0x3d, 0x19, 0x91, 0x30, 0xfb, 0x3f, 0xef, 0x62, 0xcc, 0x3e, 0xa9, 0xa0, 0xc9, 0x35, - 0xdf, 0x05, 0xc5, 0xad, 0x5e, 0x67, 0xf7, 0x4f, 0xcb, 0xa6, 0x67, 0xe0, 0x81, 0x1c, - 0xdc, 0x0c, 0xa9, 0xf3, 0xd7, 0x81, 0x76, 0x43, 0x75, 0x56, 0x47, 0xbe, 0x59, 0xdf, - 0x09, 0x6e, 0x46, 0x5e, 0xc1, 0x11, 0x24, 0x36, 0x3c, 0x98, 0x1c, 0x55, 0xd5, 0x5f, - 0x8d, 0x8a, 0xc8, 0xb6, 0x54, 0x0a, 0x98, 0xcf, 0xcc, 0x29, 0x4a, 0xa7, 0xcc, 0x62, - 0x95, 0x50, 0x85, 0x3a, 0x25, 0xbf, 0x6b, 0x32, 0x35, 0x16, 0xe1, 0x58, 0x2b, 0x4e, - 0x8b, 0x82, 0x95, 0xe2, 0x7f, 0x6b, 0x99, 0x94, 0x80, 0x2e, 0xfe, 0xf5, 0x43, 0x1f, - 0x03, 0x7d, 0x22, 0x09, 0xa0, 0x88, 0x07, 0x34, 0x6f, 0xb3, 0x9c, 0xad, 0xd8, 0x93, - 0xd6, 0x5f, 0x64, 0xc7, 0xfe, 0x92, 0xec, 0xbc, 0xdf, 0xe5, 0x55, 0x54, 0xca, 0xff, - 0xb0, 0xcf, 0x41, 0xeb, 0x5c, 0x55, 0x72, 0xba, 0x44, 0x39, 0x90, 0x00, 0xe9, 0xfa, - 0x9a, 0xaf, 0x6e, 0xb7, 0x6c, 0x2a, 0x8a, 0x5d, 0x7b, 0x6b, 0x52, 0xb9, 0xa9, 0xef, - 0x6e, 0xc3, 0xed, 0xa6, 0x65, 0xfe, 0x8a, 0xa8, 0x07, 0x48, 0xb8, 0x1f, 0x7d, 0x55, - 0x96, 0xf1, 0x94, 0x2f, 0xf7, 0x1d, 0x29, 0xc6, 0x78, 0xa3, 0xb6, 0xc6, 0x6b, 0xa7, - 0x0f, 0x45, 0xb1, 0xfc, 0xf2, 0x22, 0x38, 0x84, 0x50, 0x68, 0xf3, 0x60, 0xb0, 0x99, - 0xae, 0xe9, 0xf2, 0xf0, 0xef, 0x22, 0x33, 0x3f, 0xd6, 0x4f, 0xf1, 0x1e, 0x48, 0x15, - 0x43, 0xa5, 0x2b, 0xb3, 0x3f, 0x52, 0x3d, 0xe2, 0xec, 0x92, 0x3a, 0xe9, 0x86, 0x58, - 0x57, 0x71, 0x7b, 0x65, 0xd4, 0x4c, 0x3d, 0x9d, 0xb7, 0xb3, 0xec, 0xb2, 0xff, 0x02, - 0x25, 0x29, 0x7d, 0xeb, 0x83, 0xdd, 0x1b, 0x9a, 0x39, 0x4d, 0x69, 0x7c, 0x09, 0xd7, - 0xfe, 0xc6, 0x1e, 0xac, 0xee, 0x39, 0xa2, 0xf1, 0xce, 0xd9, 0xe6, 0xfd, 0xa5, 0xc0, - 0xf3, 0x27, 0x71, 0xc6, 0xce, 0x3f, 0x17, 0xbe, 0x0e, 0xef, 0x81, 0x10, 0x99, 0xc1, - 0x09, 0xe4, 0xfb, 0x6a, 0xec, 0x30, 0xdf, 0x04, 0x5b, 0x43, 0xda, 0x89, 0x30, 0x8b, - 0xc8, 0x37, 0x68, 0x8b, 0xb0, 0xf4, 0xa2, 0xc6, 0x04, 0xa1, 0x54, 0xa8, 0x47, 0xc5, - 0xd7, 0x87, 0x27, 0xf0, 0xe1, 0xab, 0x11, 0xe3, 0x40, 0xcf, 0xd4, 0xc7, 0xe8, 0xc6, - 0xba, 0xff, 0xfe, 0xfc, 0x74, 0xef, 0x55, 0x3d, 0x4b, 0x29, 0x26, 0x9f, 0x38, 0xb4, - 0xb7, 0xfe, 0x6e, 0x07, 0x3a, 0x70, 0xae, 0xf2, 0x0d, 0x6c, 0x23, 0x8b, 0x9f, 0xfd, - 0x24, 0x1f, 0xf6, 0x99, 0x99, 0x92, 0x30, 0xf0, 0xb3, 0x9c, 0x96, 0x3e, 0xfa, 0x00, - 0xef, 0x7f, 0x09, 0x2d, 0x76, 0x0c, 0x40, 0x9a, 0x2b, 0x6c, 0x26, 0xb4, 0x97, 0x82, - 0x9b, 0x81, 0xcb, 0xa4, 0xc8, 0x3b, 0x11, 0x44, 0xc6, 0x5a, 0x2d, 0x31, 0x78, 0xbb, - 0x28, 0xc1, 0xd8, 0xe3, 0x30, 0xd3, 0xf4, 0xaf, 0x90, 0x10, 0xad, 0x49, 0xa5, 0xdb, - 0x70, 0xd6, 0x6a, 0xf5, 0x70, 0x19, 0x21, 0x49, 0x80, 0x5f, 0xe1, 0xca, 0x61, 0xc6, - 0xd4, 0xec, 0xaf, 0xa7, 0x97, 0x51, 0x7f, 0x33, 0x06, 0xaf, 0x2a, 0x32, 0x27, 0x3b, - 0xf3, 0xd6, 0x98, 0xaa, 0x55, 0xa5, 0x72, 0xb2, 0xdf, 0x80, 0x36, 0xd9, 0x7c, 0xf5, - 0x8c, 0x12, 0x9f, 0x82, 0x85, 0xd0, 0xd7, 0xea, 0x04, 0xc1, 0x88, 0xa8, 0x39, 0x6e, - 0x73, 0x8b, 0xd4, 0x48, 0x46, 0x5e, 0x7b, 0x9a, 0x64, 0xb7, 0x96, 0x7b, 0xcb, 0x25, - 0xf8, 0xaa, 0x85, 0x9e, 0xa5, 0xca, 0x06, 0xc3, 0xdf, 0x39, 0x0f, 0xac, 0x8a, 0xc6, - 0x06, 0x05, 0x03, 0x1a, 0x02, 0x09, 0xbb, 0x80, 0x24, 0x0d, 0x05, 0x45, 0xf4, 0x11, - 0x77, 0xea, 0xb4, 0x40, 0x2e, 0x8a, 0x42, 0x3a, 0x40, 0xcc, 0xff, 0x58, 0x6b, 0x2e, - 0xdd, 0x6a, 0xcf, 0xb8, 0xf1, 0xd8, 0x0d, 0x8c, 0x60, 0x5f, 0x49, 0x05, 0x2e, 0x7a, - 0x30, 0x82, 0x6e, 0x1f, 0x03, 0x09, 0x9c, 0x71, 0x43, 0xad, 0x0b, 0x51, 0xfc, 0x63, - 0x6f, 0x1d, 0x87, 0x05, 0x83, 0xd6, 0xed, 0xce, 0xcd, 0xe9, 0x42, 0x38, 0x9e, 0x6c, - 0x01, 0x00, 0x66, 0x78, 0xda, 0xad, + 0x77, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, + 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, + 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, + 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0x51, 0x6a, 0xf6, 0xdd, + 0x77, 0xdd, 0xb6, 0xee, 0x67, 0xaa, 0xf5, 0x42, 0xce, 0xe2, 0xbe, 0xd3, 0xe4, 0xa0, + 0x7e, 0xce, 0x42, 0x8f, 0x22, 0xa8, 0x01, 0xcf, 0x01, 0xba, 0xad, 0x18, 0x27, 0xfd, + 0x42, 0x57, 0x46, 0xc5, 0x45, 0x00, 0x1c, 0x35, 0x6d, 0x0a, 0xbe, 0xaa, 0xa5, 0xa4, + 0x22, 0xdf, 0xff, 0x0e, 0xe2, 0x18, 0xac, 0x37, 0xef, 0x83, 0x97, 0xc6, 0x2c, 0xa8, + 0x6f, 0xab, 0xeb, 0xb6, 0x88, 0xb3, 0x8f, 0xb4, 0xa6, 0x54, 0x29, 0x11, 0xbe, 0x1c, + 0x5e, 0x71, 0x77, 0x8b, 0x5e, 0xb5, 0x3a, 0xf1, 0xc4, 0xcb, 0x4d, 0xd9, 0x94, 0x72, + 0x4f, 0x61, 0x0f, 0x38, 0x72, 0x4a, 0x73, 0xdf, 0x09, 0x2b, 0xea, 0xe8, 0xb8, 0x7f, + 0x7f, 0x6a, 0x2b, 0xc0, 0x9d, 0xf2, 0xaa, 0x18, 0xc2, 0xf8, 0xee, 0xba, 0x63, 0xee, + 0x0d, 0x31, 0x35, 0x3b, 0x6f, 0x28, 0x3e, 0xf5, 0x9a, 0xc1, 0x53, 0x60, 0x73, 0xda, + 0x7a, 0x6d, 0x82, 0xbf, 0xdc, 0x09, 0x74, 0x02, 0x08, 0x0f, 0xa1, 0x03, 0xcb, 0x8b, + 0x3e, 0xfb, 0x94, 0x1e, 0xe5, 0x01, 0xf6, 0x41, 0x2c, 0xfb, 0xc2, 0x50, 0xaf, 0xad, + 0xbe, 0x54, 0x4a, 0xc5, 0x1f, 0xce, 0x41, 0x5a, 0x24, 0x93, 0xba, 0x83, 0x9e, 0x38, + 0x18, 0xb0, 0xfe, 0x30, 0x18, 0xbf, 0xa4, 0x37, 0xf0, 0x6e, 0x31, 0x86, 0x14, 0x8a, + 0xa4, 0x05, 0xba, 0xb8, 0x21, 0xa2, 0x6e, 0xa0, 0x7f, 0x93, 0xcf, 0xe7, 0x56, 0x8f, + 0xe3, 0xef, 0x08, 0xfa, 0x0b, 0x80, 0xfc, 0xec, 0x5b, 0xd5, 0x91, 0x5f, 0x68, 0x8c, + 0xf5, 0x99, 0x31, 0x5e, 0x79, 0xaa, 0xea, 0x34, 0xd5, 0x18, 0xd9, 0x55, 0xfe, 0xef, + 0x30, 0x3f, 0x69, 0xb2, 0x87, 0xc6, 0xd0, 0x51, 0x6d, 0xa2, 0x39, 0xfb, 0xbd, 0xdb, + 0xaf, 0x25, 0x56, 0xeb, 0xce, 0x77, 0xa3, 0xd5, 0x97, 0x23, 0x5c, 0x22, 0xd3, 0x8c, + 0x5b, 0x5e, 0xeb, 0x98, 0xc7, 0xc0, 0x8d, 0xa8, 0xd3, 0x76, 0xbb, 0xa1, 0xb5, 0x07, + 0x85, 0xbe, 0x82, 0xbf, 0xe0, 0x9a, 0xe7, 0x1c, 0xcc, 0xaf, 0x31, 0xa2, 0xf0, 0xcf, + 0xa0, 0x76, 0xd1, 0xe4, 0xd1, 0xb5, 0x2f, 0xee, 0x45, 0xc8, 0xed, 0x23, 0xdf, 0x33, + 0xa8, 0x1c, 0xb1, 0xa8, 0xac, 0xec, 0x9f, 0x53, 0x5d, 0xa4, 0x96, 0x70, 0xf9, 0x98, + 0x6d, 0x5c, 0x92, 0xc8, 0x2b, 0x0a, 0xd2, 0x20, 0xf8, 0x5f, 0x3b, 0x38, 0x72, 0xeb, + 0xe0, 0x53, 0xcd, 0xeb, 0x96, 0x1b, 0xd2, 0xd3, 0xab, 0x3b, 0xcd, 0x67, 0x6e, 0x6f, + 0xd7, 0xcb, 0xe9, 0x79, 0x5e, 0x1f, 0x2d, 0x82, 0x87, 0x00, 0x7c, 0x91, 0x0e, 0x7b, + 0x43, 0x01, 0x69, 0xe4, 0x51, 0xf0, 0xb2, 0xd7, 0x63, 0xe5, 0x43, 0x03, 0x3b, 0xc6, + 0xc7, 0x38, 0x9f, 0xa1, 0x61, 0x5b, 0xa1, 0x9d, 0x1f, 0x27, 0x48, 0xb2, 0x17, 0xc9, + 0x60, 0xfe, 0x05, 0x04, 0x07, 0xc8, 0xf4, 0x73, 0x35, 0x6b, 0xaa, 0x6e, 0x0c, 0x7d, + 0x77, 0xfa, 0xc6, 0xc7, 0xdb, 0x45, 0x12, 0xaf, 0x57, 0x96, 0xb3, 0xbc, 0xf1, 0x23, + 0xe0, 0x90, 0xb9, 0x80, 0xeb, 0xc2, 0xd6, 0x4b, 0x86, 0xdd, 0x24, 0xcb, 0x9a, 0x6d, + 0xab, 0x1d, 0xb4, 0x13, 0x04, 0x75, 0x38, 0x90, 0x2e, 0x2e, 0x49, 0x0e, 0x4f, 0xc8, + 0x78, 0xaa, 0x04, 0xdb, 0xef, 0x66, 0x99, 0x63, 0x9c, 0x3d, 0xab, 0x17, 0xc5, 0x14, + 0x70, 0x48, 0xac, 0x6d, 0x48, 0x49, 0x0d, 0xc4, 0x88, 0x5e, 0xd9, 0x86, 0x70, 0x63, + 0x35, 0xf4, 0x1b, 0xa4, 0x15, 0x59, 0x65, 0x9e, 0x1b, 0x53, 0xda, 0x76, 0x51, 0x4c, + 0xc4, 0x0a, 0xdb, 0x66, 0xc3, 0x5c, 0xe5, 0x6f, 0x3a, 0xbe, 0x39, 0xe1, 0xae, 0xe5, + 0x84, 0x9f, 0xff, 0xcc, 0x6e, 0x1f, 0x1b, 0xf8, 0x11, 0xce, 0xb6, 0x65, 0xa6, 0xfc, + 0xf8, 0x80, 0x6b, 0xbb, 0xba, 0x4a, 0x5b, 0x87, 0x38, 0xa1, 0x17, 0xdc, 0xaf, 0xfb, + 0x4f, 0xdf, 0x10, 0x08, 0x00, 0x6f, ], ock: [ - 0xf9, 0x59, 0x87, 0xcc, 0x0c, 0x73, 0x57, 0xc7, 0x20, 0x26, 0x27, 0xa5, 0xa5, 0x50, - 0x09, 0xef, 0xd7, 0x17, 0x55, 0x3e, 0x9d, 0x34, 0xc1, 0x5f, 0xad, 0xf5, 0xc9, 0x46, - 0xa9, 0xa0, 0x72, 0x17, + 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, + 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, + 0x81, 0xf0, 0x8c, 0xfb, ], op: [ 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, - 0x6b, 0x80, 0xbb, 0xb7, 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, - 0xbf, 0xb7, 0x8a, 0xec, 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, - 0x77, 0xc9, 0x46, 0xe9, 0xcd, 0x7a, 0x24, 0x23, + 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, + 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, + 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, ], c_out: [ - 0x28, 0x9d, 0x00, 0xd4, 0x62, 0x78, 0x0b, 0xdb, 0xb6, 0xcd, 0x6c, 0xec, 0x93, 0x6b, - 0xe6, 0x5e, 0x63, 0x0d, 0x4a, 0x3c, 0x2a, 0xf7, 0x6e, 0x10, 0x4b, 0x17, 0x4e, 0x3d, - 0x5b, 0x71, 0x66, 0x39, 0xb0, 0x68, 0xb3, 0x85, 0x00, 0xd8, 0x04, 0x00, 0xee, 0x64, - 0x2f, 0x8e, 0x08, 0xc8, 0xdb, 0x29, 0xff, 0xd5, 0xa9, 0xda, 0xde, 0x84, 0xa5, 0x49, - 0x5d, 0x57, 0x7b, 0x2f, 0x56, 0xd3, 0x2b, 0x07, 0x96, 0xca, 0x23, 0xf0, 0x0f, 0x0f, - 0x8e, 0xf9, 0x93, 0x07, 0x4f, 0x88, 0x0d, 0x6a, 0xeb, 0xcb, + 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, + 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, + 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, + 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, + 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, + 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, ], }, TestVector { @@ -1560,34 +1560,34 @@ pub(crate) fn test_vectors() -> Vec { 0xe2, 0x3c, 0x39, 0x11, ], nf_old: [ - 0x35, 0x6f, 0xc7, 0x2e, 0x1b, 0xf1, 0xe3, 0xa2, 0xa5, 0x9a, 0xa9, 0xe4, 0x75, 0x15, - 0x5c, 0xf7, 0x43, 0xf8, 0xfd, 0xf0, 0xd1, 0x5b, 0x4c, 0xc4, 0x02, 0x60, 0xd0, 0xd0, - 0x9a, 0xda, 0x04, 0x08, + 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, + 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, + 0x3e, 0xe8, 0xed, 0x20, ], cmx: [ - 0xca, 0xa2, 0x8a, 0x69, 0x04, 0x54, 0x66, 0x37, 0xa7, 0xd4, 0xe5, 0xfb, 0xc2, 0x65, - 0x4c, 0xbf, 0x24, 0x4d, 0x18, 0x77, 0x9d, 0x35, 0x62, 0x25, 0x6c, 0x14, 0xd5, 0xb1, - 0x00, 0x5d, 0xc6, 0x0f, + 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, + 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, + 0x32, 0x4a, 0xe9, 0x04, ], esk: [ - 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, 0x42, 0x0e, 0xff, 0xd7, - 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, 0x91, 0x90, 0x01, 0xf8, - 0x66, 0xa8, 0xe9, 0x2c, + 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, + 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, + 0x99, 0x07, 0xea, 0x0c, ], ephemeral_key: [ - 0x00, 0x62, 0x7e, 0x29, 0xc1, 0x83, 0x3e, 0x4e, 0x8f, 0xad, 0xe0, 0x82, 0x52, 0xf3, - 0x83, 0x67, 0x78, 0xb9, 0x39, 0x4c, 0x1f, 0xfe, 0xab, 0x70, 0xbf, 0x35, 0x93, 0xd5, - 0x9a, 0x81, 0xa0, 0xa5, + 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, + 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, + 0x05, 0xc0, 0x61, 0x23, ], shared_secret: [ - 0xa9, 0x93, 0x34, 0x1f, 0x99, 0xeb, 0xa8, 0x2d, 0xb6, 0xec, 0x5e, 0x71, 0x3e, 0xe2, - 0x9c, 0x01, 0xf4, 0xce, 0x2a, 0x8b, 0xb6, 0xb5, 0xeb, 0xb6, 0x0b, 0xa6, 0xeb, 0xa9, - 0x6b, 0xa4, 0x17, 0x9b, + 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, + 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, + 0x98, 0xa0, 0xd0, 0x00, ], k_enc: [ - 0x35, 0x81, 0x19, 0x19, 0x3c, 0x9d, 0x2a, 0xb6, 0xd4, 0x95, 0xe0, 0x19, 0xf9, 0x7a, - 0x1c, 0x41, 0x30, 0xae, 0xe6, 0x3d, 0xae, 0xc6, 0xbb, 0xa2, 0xf2, 0x74, 0x40, 0x0f, - 0xd3, 0x4f, 0xad, 0x28, + 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, + 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, + 0x40, 0x8c, 0x2e, 0xfe, ], p_enc: [ 0x02, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, @@ -1633,68 +1633,68 @@ pub(crate) fn test_vectors() -> Vec { 0x84, 0x37, 0x3f, 0x4f, ], c_enc: [ - 0x31, 0xac, 0xda, 0xa6, 0xc1, 0x76, 0xbb, 0x7a, 0x2c, 0x7d, 0x66, 0x09, 0xdc, 0x2c, - 0x5e, 0x7b, 0x2e, 0xe7, 0x1d, 0xa9, 0x3c, 0x73, 0x87, 0x52, 0x74, 0xfa, 0x6c, 0x2a, - 0xd6, 0x26, 0x13, 0xc7, 0x18, 0x9b, 0x35, 0x33, 0xec, 0xf0, 0x34, 0xd8, 0x76, 0xc7, - 0x26, 0xf1, 0xed, 0x99, 0x43, 0xd4, 0x45, 0x07, 0x87, 0x52, 0x75, 0xa8, 0xe3, 0x71, - 0x0a, 0x11, 0x8d, 0x91, 0x64, 0x72, 0x91, 0x28, 0x6c, 0xf8, 0x80, 0xa7, 0x82, 0xab, - 0xea, 0xa8, 0xa6, 0xc3, 0x2f, 0xdf, 0x6f, 0x30, 0x4b, 0x0e, 0xe5, 0xbc, 0xb1, 0x4b, - 0x82, 0x79, 0x2a, 0xa3, 0xaf, 0xd7, 0x24, 0x3f, 0x57, 0xb7, 0xdc, 0xa7, 0x93, 0x52, - 0x19, 0xdf, 0x98, 0x2c, 0xe1, 0x28, 0xae, 0xa6, 0xf6, 0xbd, 0x18, 0xe1, 0x30, 0x7e, - 0xba, 0x0e, 0x3d, 0xb0, 0x06, 0x14, 0xc2, 0x65, 0xc6, 0xf2, 0x8b, 0xfe, 0x58, 0xc1, - 0x1d, 0x4a, 0xc9, 0x6d, 0x49, 0x02, 0x96, 0x7b, 0x54, 0xbc, 0x5d, 0xd1, 0x5c, 0x14, - 0x3f, 0xf4, 0x2b, 0xbb, 0x62, 0xb9, 0x34, 0xb0, 0x9e, 0x79, 0xb6, 0x1e, 0xaf, 0xe7, - 0x9a, 0xbc, 0x86, 0x94, 0x47, 0x5b, 0x6c, 0x8e, 0x19, 0x94, 0xba, 0x05, 0x5e, 0xa3, - 0xc1, 0x82, 0x93, 0xb0, 0x3c, 0x42, 0x49, 0x50, 0x1d, 0xfd, 0xc0, 0x14, 0x60, 0xcf, - 0x78, 0xcd, 0x97, 0x51, 0x30, 0xae, 0x34, 0x05, 0xba, 0x7d, 0xdc, 0x71, 0x30, 0xcb, - 0xdb, 0xb9, 0x8c, 0x7a, 0xaf, 0x6b, 0x1d, 0x0b, 0x44, 0xa5, 0x16, 0x79, 0xaa, 0x63, - 0x0a, 0x43, 0xae, 0x23, 0xb3, 0xd2, 0x2f, 0x73, 0x4c, 0xe1, 0xdb, 0xed, 0xea, 0x17, - 0x5a, 0x00, 0x62, 0xb0, 0x6e, 0x23, 0xf4, 0xd0, 0x6d, 0x2a, 0xd0, 0x45, 0xae, 0x98, - 0x2d, 0xb4, 0x34, 0x8f, 0x20, 0xc8, 0x9b, 0xf9, 0x67, 0x0e, 0x2f, 0xda, 0x47, 0x2e, - 0x55, 0xce, 0x4c, 0x35, 0x82, 0xb7, 0x64, 0x43, 0xe0, 0xab, 0xbb, 0x77, 0x8a, 0xec, - 0xa0, 0xf3, 0x9c, 0x55, 0xb6, 0xab, 0xbe, 0xd8, 0x1f, 0xde, 0x89, 0xad, 0x2c, 0x56, - 0x7d, 0xfe, 0x27, 0x7b, 0xb2, 0x69, 0xac, 0x6a, 0xe0, 0xe1, 0x88, 0x39, 0x8d, 0xea, - 0x24, 0xad, 0xcc, 0xe1, 0x82, 0xe7, 0xfd, 0xdc, 0x80, 0xeb, 0xd7, 0x69, 0xd0, 0xf0, - 0x76, 0xf9, 0xaf, 0x2d, 0xd9, 0x83, 0x07, 0xa5, 0x27, 0xc6, 0x99, 0x42, 0xdf, 0xa3, - 0xe7, 0xf4, 0x86, 0x76, 0x10, 0x1a, 0x47, 0xeb, 0x07, 0x80, 0xb6, 0x90, 0xb1, 0xaf, - 0x10, 0xfc, 0xfb, 0x5e, 0xe2, 0xbd, 0x40, 0xd2, 0x7d, 0x10, 0x9b, 0xa1, 0x5a, 0xb0, - 0xb1, 0xe9, 0x55, 0x4f, 0xdd, 0xfa, 0x81, 0x6b, 0x99, 0xcd, 0x8f, 0xdd, 0xe6, 0x81, - 0xae, 0x6b, 0x6c, 0xbb, 0xfb, 0xf0, 0x2c, 0x36, 0x32, 0x68, 0xd0, 0xf3, 0xc6, 0xa7, - 0x26, 0x1b, 0x6d, 0x00, 0x87, 0xbc, 0xad, 0xb6, 0xfb, 0x9b, 0xf3, 0x93, 0x04, 0xfc, - 0x08, 0x41, 0x5d, 0x83, 0x6f, 0xe4, 0x09, 0xa4, 0x3f, 0xaf, 0x9e, 0x28, 0xfb, 0x48, - 0x3f, 0x4a, 0x47, 0xaa, 0xd7, 0xe1, 0xf7, 0x97, 0x30, 0xb3, 0x21, 0x53, 0x60, 0x80, - 0xdb, 0x35, 0x12, 0x48, 0xb2, 0x66, 0x9b, 0x6e, 0x74, 0x48, 0x90, 0x87, 0xae, 0x72, - 0xba, 0x15, 0xd2, 0xae, 0xdd, 0x0c, 0x1e, 0x7e, 0xb1, 0x5a, 0x2f, 0x5a, 0x77, 0x31, - 0xeb, 0x45, 0xa6, 0x17, 0x8a, 0x44, 0x87, 0x09, 0x31, 0xec, 0x8e, 0x34, 0x8c, 0x19, - 0x2b, 0xc8, 0x87, 0xc8, 0x63, 0x60, 0x56, 0x67, 0x6f, 0x58, 0xd0, 0xc6, 0x34, 0xfc, - 0x99, 0xea, 0x7b, 0x07, 0xfa, 0x1b, 0x62, 0x99, 0xae, 0x5d, 0xbf, 0xe0, 0x84, 0x45, - 0xad, 0x99, 0x9f, 0x45, 0xdf, 0x00, 0xf1, 0xa4, 0x7a, 0xa5, 0xef, 0x6f, 0x88, 0xcd, - 0xba, 0x80, 0xc8, 0x8f, 0x94, 0x01, 0xe6, 0xe9, 0x09, 0xca, 0x2c, 0x5d, 0xe2, 0xcf, - 0x8f, 0x6a, 0x98, 0x44, 0xca, 0x32, 0xfe, 0x91, 0xf7, 0x13, 0xfe, 0x10, 0xa0, 0x69, - 0x8a, 0x1b, 0x3b, 0xfd, 0xf4, 0x47, 0x43, 0x75, 0xb4, 0x79, 0x1d, 0xc8, 0x50, 0x50, - 0xc9, 0x28, 0x90, 0x0e, 0x73, 0x1f, 0x7c, 0x4a, 0x12, 0x9d, 0x8e, 0x21, 0xfc, 0xf4, - 0x17, 0x62, 0x7c, 0x47, 0xdd, 0xc9, 0xf5, 0x88, 0x40, 0x38, 0x41, 0x31, 0x7a, 0x9a, - 0xc2, 0x6e, 0xef, 0x6c, 0xda, 0x23, + 0x2d, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, + 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, + 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, + 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0xc5, 0xa4, 0x6c, 0x3a, + 0x74, 0x12, 0xdf, 0x11, 0xc5, 0xda, 0x16, 0xb4, 0xdd, 0x22, 0x90, 0x1a, 0x59, 0x2b, + 0x0e, 0x93, 0x29, 0x77, 0xba, 0x06, 0x67, 0x3d, 0x6f, 0xd0, 0x38, 0xac, 0xba, 0xa9, + 0xbf, 0x79, 0xc1, 0x5b, 0xa6, 0x2b, 0x6e, 0x30, 0x74, 0xef, 0x95, 0x3b, 0x81, 0x4c, + 0xf1, 0xbd, 0xf0, 0x15, 0x77, 0xed, 0x3e, 0x3f, 0xae, 0xf4, 0x71, 0x55, 0xc9, 0x1c, + 0x68, 0xee, 0x32, 0x88, 0x1b, 0x73, 0x74, 0x94, 0xb3, 0xb4, 0x76, 0x08, 0x3b, 0x3b, + 0xd1, 0x77, 0x93, 0xc4, 0x98, 0x93, 0x1e, 0xaa, 0x92, 0xb1, 0x7c, 0x7d, 0x10, 0x47, + 0x58, 0xfc, 0x8b, 0x34, 0x93, 0xd2, 0x47, 0x41, 0x7f, 0x5e, 0xc1, 0x97, 0x9a, 0x35, + 0x28, 0x93, 0xe9, 0x95, 0x63, 0xb6, 0xc3, 0xab, 0x95, 0xcc, 0x5a, 0xfa, 0x37, 0x32, + 0xef, 0xae, 0xce, 0x9e, 0x74, 0x32, 0xc8, 0x04, 0x15, 0xe2, 0x5f, 0x55, 0x56, 0x53, + 0xc7, 0xda, 0x5d, 0xb0, 0xcc, 0x61, 0x08, 0x74, 0x21, 0x95, 0x9b, 0xb1, 0xdf, 0x80, + 0x03, 0xb7, 0x3d, 0xa0, 0xbe, 0xf0, 0x60, 0xf3, 0xa8, 0x4c, 0x8b, 0xc2, 0x4c, 0xc7, + 0x6d, 0x0d, 0x9e, 0x9c, 0x33, 0x76, 0x5c, 0x20, 0xf0, 0x7d, 0x80, 0xe2, 0x0f, 0xdf, + 0x27, 0x81, 0x5d, 0xbd, 0x9d, 0x71, 0x7c, 0x09, 0x66, 0xf8, 0x0b, 0x94, 0xb9, 0x59, + 0x15, 0x08, 0x1e, 0xa4, 0x55, 0x37, 0xa5, 0xa0, 0x74, 0xb9, 0xc9, 0x4b, 0x43, 0xdd, + 0xf4, 0xa9, 0xcb, 0xad, 0xe9, 0x04, 0x51, 0x0e, 0xaa, 0x96, 0x9e, 0x66, 0x6c, 0x94, + 0x34, 0xb9, 0xf6, 0x3e, 0xae, 0x62, 0xad, 0x58, 0x27, 0x99, 0x62, 0xe9, 0x41, 0x33, + 0x05, 0x5c, 0xbc, 0xc4, 0xb1, 0x55, 0xc0, 0x0f, 0x1b, 0x83, 0xff, 0x41, 0x28, 0xa8, + 0xab, 0xb4, 0xce, 0x68, 0xe9, 0xf1, 0xe3, 0x08, 0xe6, 0xf9, 0x7e, 0x51, 0x3a, 0xf5, + 0x95, 0x47, 0x1a, 0x16, 0x77, 0xef, 0x78, 0xe9, 0x77, 0x0f, 0x43, 0xad, 0xde, 0x1a, + 0x64, 0x58, 0x6d, 0xe6, 0xa5, 0x87, 0xc3, 0xd6, 0x93, 0xfe, 0xa8, 0xfc, 0xc6, 0xac, + 0xc8, 0x94, 0x96, 0x1e, 0x2f, 0x47, 0xb2, 0x02, 0xe8, 0x6a, 0x57, 0x38, 0x79, 0xb5, + 0xbf, 0xd7, 0x29, 0xda, 0x2f, 0xbe, 0xfc, 0x64, 0x5c, 0xfa, 0xb1, 0x88, 0x0d, 0x51, + 0x76, 0x40, 0xdf, 0x5f, 0x53, 0xe5, 0x7c, 0x72, 0xd6, 0x5a, 0x63, 0x3a, 0xa5, 0x36, + 0xb2, 0x98, 0x34, 0xbf, 0x28, 0x16, 0xb1, 0xf7, 0x16, 0xbf, 0x43, 0x6d, 0x6b, 0x2b, + 0x6e, 0x47, 0x73, 0x28, 0xc9, 0x58, 0xa6, 0xb8, 0xcf, 0x73, 0xb9, 0x5d, 0x22, 0xf6, + 0x99, 0x3b, 0x3f, 0xc5, 0x25, 0xdb, 0x62, 0x7f, 0x6f, 0x38, 0xd0, 0x77, 0x9a, 0x1d, + 0x39, 0xaf, 0x05, 0xed, 0x74, 0xfd, 0xfe, 0xff, 0x98, 0x7a, 0x95, 0x88, 0xd8, 0x0b, + 0x7e, 0x79, 0x69, 0x4a, 0xe4, 0x55, 0x29, 0x29, 0x88, 0x1c, 0x5b, 0xfe, 0x20, 0x49, + 0x2f, 0xd6, 0xf3, 0x37, 0xca, 0x88, 0xdf, 0xb5, 0x01, 0xe5, 0x45, 0xd2, 0x36, 0x73, + 0xac, 0xac, 0xbc, 0x3d, 0x33, 0x14, 0xa8, 0xbb, 0xf5, 0xec, 0x70, 0xb7, 0x05, 0xcc, + 0x9d, 0x26, 0x57, 0xbd, 0xd5, 0xa7, 0x09, 0x15, 0xbe, 0xf6, 0xd0, 0xf0, 0x39, 0xd3, + 0xeb, 0xa6, 0xbb, 0x71, 0x5b, 0xe5, 0x1e, 0xbf, 0x6e, 0xf6, 0x59, 0xea, 0x32, 0xff, + 0x80, 0xc8, 0x2c, 0x04, 0x21, 0x67, 0x5f, 0xe3, 0x71, 0xef, 0x49, 0xf1, 0xb9, 0xe3, + 0x8f, 0x43, 0x7b, 0x4a, 0x76, 0x55, 0xdc, 0x29, 0x16, 0xaa, 0x30, 0x86, 0xde, 0x6c, + 0x62, 0xa8, 0x2b, 0x36, 0x1c, 0x05, 0x3f, 0xc6, 0x34, 0x54, 0xcc, 0xd0, 0x2c, 0x22, + 0xd4, 0x1f, 0xf5, 0xbb, 0x83, 0x62, 0xde, 0xaa, 0x70, 0x82, 0x5a, 0xd2, 0xf9, 0x93, + 0x63, 0x9f, 0xc4, 0x46, 0x06, 0x9d, 0x78, 0xa6, 0x1d, 0x33, 0x8d, 0xf5, 0x8f, 0x77, + 0x63, 0xe3, 0x55, 0xe6, 0xa9, 0xff, ], ock: [ - 0x9c, 0x10, 0x3d, 0xd5, 0xd6, 0x38, 0x6c, 0xdd, 0x67, 0x69, 0x51, 0xe6, 0x56, 0x4b, - 0x16, 0x6b, 0xc5, 0xc5, 0x72, 0x32, 0xcf, 0xc3, 0x1e, 0x0e, 0x69, 0xce, 0x84, 0xda, - 0xe8, 0x32, 0x76, 0xbe, + 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, + 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, + 0x01, 0xd9, 0xfb, 0xa3, ], op: [ 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, - 0x17, 0x5b, 0xa9, 0x8b, 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, - 0x42, 0x0e, 0xff, 0xd7, 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, - 0x91, 0x90, 0x01, 0xf8, 0x66, 0xa8, 0xe9, 0x2c, + 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, + 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, + 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, ], c_out: [ - 0xdf, 0x6b, 0xb6, 0x2e, 0x3b, 0x64, 0xf7, 0xe9, 0x37, 0xc1, 0xde, 0x38, 0xaa, 0xc5, - 0xe6, 0xb1, 0x61, 0x35, 0xba, 0x2f, 0x9d, 0xbe, 0xed, 0xb0, 0x7a, 0x45, 0xb6, 0xf0, - 0x9d, 0xf3, 0xeb, 0xec, 0xac, 0x04, 0x6c, 0x61, 0x92, 0xfb, 0xe8, 0x95, 0xd2, 0x31, - 0x02, 0x77, 0xb3, 0xe0, 0x3a, 0x90, 0xfd, 0xc8, 0x53, 0x48, 0x4a, 0x01, 0x5c, 0x88, - 0xd6, 0x63, 0x2e, 0x97, 0xba, 0x98, 0xad, 0xca, 0x9e, 0x49, 0xf5, 0x38, 0xc3, 0xa7, - 0xcb, 0x6d, 0x77, 0x23, 0xbd, 0xcc, 0x9c, 0x03, 0xae, 0x88, + 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, + 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, + 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, + 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, + 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, + 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, ], }, TestVector { @@ -1769,34 +1769,34 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0xe5, 0x05, 0xad, ], nf_old: [ - 0x32, 0x91, 0x87, 0x35, 0x66, 0x3f, 0x34, 0xad, 0xa0, 0x22, 0x8a, 0xea, 0x4a, 0xcc, - 0x19, 0x2a, 0x12, 0x3f, 0xcf, 0xa0, 0x60, 0x46, 0x89, 0xf9, 0x1a, 0xcb, 0xe9, 0x38, - 0x31, 0xe4, 0x8c, 0x0c, + 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, + 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, + 0x45, 0x89, 0x35, 0x14, ], cmx: [ - 0xde, 0x7b, 0xf1, 0x55, 0x08, 0x29, 0x51, 0x96, 0x0a, 0x10, 0xbb, 0x8b, 0x75, 0x41, - 0x02, 0x43, 0x0f, 0x89, 0xf5, 0x32, 0x67, 0x24, 0x04, 0x36, 0x81, 0xf5, 0x06, 0xf7, - 0x48, 0xe2, 0x6f, 0x07, + 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, + 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, + 0xc7, 0x4d, 0x19, 0x1b, ], esk: [ - 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, 0x59, 0xa1, 0x33, 0xf3, - 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, 0xdd, 0x63, 0xe0, 0x62, - 0x83, 0x05, 0x47, 0x08, + 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, + 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, + 0x99, 0xbd, 0x4c, 0x13, ], ephemeral_key: [ - 0x18, 0x20, 0x84, 0x5b, 0x2d, 0x90, 0xe5, 0x45, 0x76, 0x0f, 0xca, 0x4d, 0xab, 0x30, - 0xa6, 0x78, 0x3e, 0x03, 0x1c, 0x0e, 0x54, 0x28, 0xcc, 0x22, 0x6f, 0x3f, 0x40, 0x1d, - 0xec, 0x20, 0x0b, 0x11, + 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, + 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, + 0x0e, 0x12, 0xbc, 0x1e, ], shared_secret: [ - 0x79, 0x38, 0x77, 0xa1, 0xae, 0xda, 0xe9, 0xac, 0x6d, 0xa3, 0xd7, 0xe8, 0x02, 0xb5, - 0xbc, 0x77, 0x3c, 0x0d, 0x93, 0x1c, 0x79, 0x6d, 0x17, 0x0c, 0x59, 0x7f, 0x22, 0xba, - 0x6f, 0xcc, 0xa2, 0x06, + 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, + 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, + 0x5c, 0xb8, 0xf3, 0x31, ], k_enc: [ - 0x28, 0x20, 0xb9, 0x38, 0xd6, 0xfc, 0xea, 0x99, 0xa7, 0x23, 0x37, 0x50, 0xa0, 0xf0, - 0x9a, 0x32, 0x10, 0xad, 0x91, 0x73, 0x46, 0x16, 0x6a, 0xea, 0xdc, 0x89, 0xbb, 0x50, - 0xf4, 0x54, 0x50, 0xa3, + 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, + 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, + 0xf2, 0x2f, 0x9f, 0xf8, ], p_enc: [ 0x02, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, @@ -1842,68 +1842,68 @@ pub(crate) fn test_vectors() -> Vec { 0x3e, 0xcc, 0xc6, 0x23, ], c_enc: [ - 0xd9, 0x6a, 0xe8, 0x2f, 0xba, 0xff, 0xb9, 0xe4, 0xbd, 0x36, 0x47, 0x57, 0x96, 0x33, - 0xbc, 0x8a, 0x89, 0x66, 0xae, 0x4e, 0x18, 0x85, 0x99, 0xdc, 0x3c, 0xf0, 0x30, 0x41, - 0xd2, 0x64, 0x4f, 0x60, 0x3c, 0xe5, 0x56, 0x2e, 0x7f, 0xa1, 0xd3, 0x83, 0x12, 0x79, - 0xb6, 0x32, 0x60, 0x4d, 0x06, 0x5e, 0xd2, 0x46, 0xad, 0x2d, 0x4f, 0x73, 0xf3, 0xa4, - 0x1b, 0x2a, 0x27, 0x99, 0xe5, 0xba, 0xf8, 0x6e, 0x7d, 0x9f, 0xcc, 0x64, 0xd5, 0x6b, - 0xde, 0x56, 0xcb, 0xb0, 0x01, 0xeb, 0x7c, 0x7c, 0x0c, 0xf1, 0xe2, 0xae, 0xc3, 0xce, - 0xb1, 0x49, 0x2d, 0xdf, 0x4e, 0x35, 0x20, 0x76, 0x1f, 0x70, 0xf6, 0xa9, 0x5c, 0x9e, - 0xde, 0xed, 0x51, 0x43, 0x6d, 0xca, 0xcf, 0x71, 0x1e, 0xb5, 0x53, 0x24, 0xd3, 0xf0, - 0x1d, 0xcc, 0xa0, 0x1b, 0xca, 0x15, 0xba, 0xf2, 0x8f, 0xed, 0x81, 0x4c, 0xc3, 0x3a, - 0x43, 0x6b, 0xbc, 0x08, 0x60, 0x56, 0x78, 0x55, 0xa4, 0x9f, 0x5e, 0xfd, 0x49, 0xea, - 0x78, 0x30, 0xc2, 0xf6, 0x00, 0x61, 0xd8, 0x13, 0xa8, 0x49, 0xb4, 0x40, 0xb1, 0x2e, - 0x8f, 0x31, 0xe2, 0xdc, 0x0c, 0x39, 0x4c, 0xeb, 0x92, 0x4f, 0x0d, 0xc6, 0xd5, 0x7b, - 0xcc, 0x39, 0x1d, 0x4a, 0x5f, 0x56, 0x9f, 0x34, 0x74, 0x6b, 0x9d, 0x92, 0x08, 0x82, - 0x25, 0xb1, 0xaa, 0x3e, 0x90, 0x6f, 0x6d, 0xe4, 0xa7, 0x92, 0x2a, 0xc1, 0x16, 0xac, - 0xb2, 0x78, 0xe8, 0xef, 0xbb, 0xf6, 0xf1, 0xe3, 0xe0, 0x8d, 0x66, 0xb3, 0x4d, 0x6e, - 0xde, 0x34, 0xae, 0x78, 0x40, 0xa8, 0x80, 0x2b, 0x7c, 0x10, 0x0f, 0xa7, 0x98, 0x46, - 0x4d, 0xb5, 0x29, 0x45, 0xdb, 0xbe, 0x35, 0xe7, 0x7a, 0x77, 0x21, 0xb2, 0xe0, 0xf8, - 0xb9, 0xa1, 0x0f, 0x6b, 0xf9, 0xa2, 0x80, 0x8f, 0xa5, 0x85, 0xff, 0x21, 0xb0, 0xa3, - 0xaf, 0xfd, 0x5f, 0x3c, 0xb2, 0x30, 0x63, 0x4e, 0x2e, 0x43, 0xff, 0xde, 0x6d, 0x09, - 0x0a, 0xfc, 0xc6, 0x70, 0x4d, 0x7b, 0x3f, 0xc6, 0x15, 0x44, 0x85, 0x3b, 0xcd, 0xa7, - 0xa1, 0x06, 0xd8, 0x5b, 0xd8, 0xd8, 0x6c, 0x6f, 0x8c, 0xe0, 0x34, 0x01, 0x6e, 0xd9, - 0xa3, 0x69, 0x46, 0xf8, 0x52, 0x8b, 0x6f, 0x1e, 0x1a, 0x19, 0x82, 0xd6, 0x8d, 0x38, - 0x86, 0xe5, 0xea, 0xe6, 0xc1, 0xe3, 0x88, 0xf3, 0xde, 0xad, 0x0d, 0x35, 0x3b, 0x6c, - 0x0c, 0xbf, 0x57, 0xc2, 0xe4, 0x7d, 0x30, 0x72, 0x3e, 0xac, 0x95, 0x7b, 0x4a, 0xec, - 0x82, 0xc8, 0xa1, 0x00, 0x9e, 0x3d, 0x71, 0x96, 0x92, 0xb2, 0xfc, 0xbd, 0xda, 0xae, - 0x62, 0x5a, 0x89, 0x6a, 0x47, 0x29, 0x85, 0xb7, 0x9e, 0xb6, 0x2b, 0x1f, 0xe3, 0x3d, - 0x6e, 0x27, 0xbc, 0x1f, 0x10, 0xe4, 0xfe, 0x5c, 0x06, 0xb2, 0x4c, 0x59, 0x7f, 0x72, - 0x3c, 0x67, 0x13, 0x36, 0x13, 0xae, 0x8e, 0x15, 0x4d, 0x81, 0x69, 0x78, 0xb8, 0xfc, - 0xa6, 0x50, 0xc0, 0x1d, 0x77, 0x1a, 0x62, 0x69, 0x2a, 0x84, 0x82, 0x94, 0x2e, 0x28, - 0xfe, 0xf0, 0x45, 0x19, 0x9e, 0xd1, 0xa6, 0x64, 0x99, 0xeb, 0xa1, 0xee, 0xc1, 0x9a, - 0xc8, 0x4a, 0x12, 0xe4, 0x10, 0x29, 0xd2, 0x2f, 0x21, 0x87, 0x6e, 0xd7, 0x4a, 0x76, - 0xef, 0x39, 0xa0, 0x57, 0xce, 0x0a, 0x15, 0x8e, 0x68, 0x51, 0xec, 0x35, 0x6d, 0x97, - 0x7b, 0x1a, 0xa6, 0x8d, 0xcf, 0x70, 0x88, 0xa9, 0xf0, 0xf9, 0xe4, 0x75, 0xa2, 0xbb, - 0xc1, 0xc4, 0x49, 0x5b, 0x54, 0x6f, 0xff, 0xed, 0xaa, 0x66, 0xc4, 0xf9, 0x51, 0x74, - 0xc6, 0x2f, 0x56, 0x5a, 0x3c, 0xc0, 0xac, 0xaf, 0x85, 0x4a, 0xde, 0xd4, 0xb4, 0x25, - 0xa0, 0xc7, 0xdb, 0xcd, 0x37, 0x42, 0xa7, 0xe0, 0x59, 0x2e, 0x83, 0x73, 0x41, 0xf8, - 0x95, 0x32, 0x90, 0x99, 0xe1, 0x70, 0xb6, 0xff, 0xb1, 0x05, 0xfd, 0xbc, 0x77, 0x29, - 0x8e, 0x8c, 0x0f, 0x5e, 0xeb, 0x9e, 0x99, 0xc6, 0x58, 0x4b, 0xcf, 0xf1, 0x20, 0x20, - 0x9d, 0x69, 0x22, 0xb5, 0x34, 0xbe, 0xc9, 0xfa, 0xc1, 0xd7, 0xd2, 0x74, 0xdb, 0xcb, - 0x4a, 0x12, 0xea, 0x5a, 0x99, 0x21, 0x39, 0x2f, 0x00, 0x96, 0x60, 0x29, 0xff, 0x26, - 0x0e, 0xd2, 0x4c, 0x32, 0x78, 0x58, 0xe0, 0x34, 0x64, 0x0a, 0x8c, 0xfb, 0x28, 0xad, - 0x97, 0xe5, 0x3d, 0x80, 0xe1, 0xc9, + 0x72, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, + 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, + 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, + 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0x35, 0xef, 0x4c, 0x51, + 0x8c, 0x77, 0xd6, 0x22, 0x28, 0xe1, 0xe4, 0xa1, 0x35, 0xca, 0x6c, 0xb4, 0xed, 0x5a, + 0xbb, 0xdf, 0x3e, 0x81, 0xd0, 0x96, 0x50, 0xa8, 0xfa, 0x9b, 0x5c, 0x3d, 0x05, 0xb6, + 0xda, 0xcf, 0x3c, 0x3d, 0xb3, 0xb3, 0x63, 0xe4, 0x10, 0x57, 0x23, 0x70, 0x0c, 0x69, + 0x13, 0x9f, 0x81, 0xec, 0xc4, 0x8d, 0x88, 0x3d, 0xa0, 0x39, 0xdd, 0xed, 0x5e, 0xf6, + 0x04, 0x0a, 0xb2, 0x12, 0x0e, 0x53, 0x3b, 0x1f, 0xfd, 0x06, 0x74, 0xdb, 0x5b, 0x92, + 0x6e, 0x58, 0x7f, 0x16, 0xe7, 0xe8, 0x96, 0x2b, 0x12, 0x48, 0x35, 0xbd, 0x56, 0xcf, + 0xd8, 0xe7, 0x5b, 0xf6, 0xaa, 0x4d, 0xcd, 0x4d, 0x6f, 0x0b, 0x55, 0x61, 0x71, 0x9c, + 0x80, 0xaa, 0x82, 0xb3, 0xbc, 0xea, 0x16, 0x7a, 0x31, 0xc6, 0x69, 0x87, 0x61, 0xe2, + 0xd2, 0x6c, 0xb5, 0x6d, 0xd3, 0x04, 0x16, 0x72, 0x1c, 0x93, 0x37, 0x32, 0x92, 0x85, + 0x33, 0x58, 0xfa, 0xfe, 0x74, 0x95, 0x55, 0x8d, 0xb9, 0x9e, 0x47, 0xa3, 0xa1, 0x6e, + 0xd2, 0x2c, 0xdb, 0x9d, 0x7d, 0x16, 0xcf, 0xd9, 0xa7, 0xbb, 0x55, 0x9c, 0x72, 0x86, + 0xed, 0x84, 0xf8, 0x89, 0x9c, 0xb0, 0x52, 0x2e, 0x8a, 0x49, 0x7f, 0x3e, 0x14, 0x45, + 0x2b, 0xa8, 0xa9, 0x4a, 0x7f, 0x58, 0xe5, 0xde, 0x37, 0x1d, 0x76, 0xec, 0xc9, 0xef, + 0xe2, 0x0a, 0xe7, 0x9b, 0xee, 0x12, 0xbc, 0xe4, 0xe4, 0xb6, 0xf2, 0x35, 0x35, 0xe5, + 0xc3, 0xc4, 0x3a, 0x4c, 0xa2, 0x07, 0x6f, 0xd6, 0x73, 0xf0, 0x80, 0x6f, 0xa9, 0x85, + 0xc5, 0x88, 0xd1, 0x14, 0xc0, 0x7d, 0x8c, 0xe3, 0xa2, 0x33, 0xe5, 0x4d, 0x77, 0x11, + 0x6c, 0x8a, 0x2a, 0x56, 0xa6, 0x82, 0xe7, 0xa4, 0x85, 0xdf, 0x71, 0xb3, 0x02, 0xa0, + 0x36, 0xdd, 0xab, 0x21, 0x4d, 0xee, 0x77, 0x62, 0x19, 0xcc, 0x24, 0x25, 0x94, 0xf7, + 0x5b, 0x8e, 0xbd, 0x56, 0x6d, 0x74, 0xb1, 0x6c, 0x9e, 0xc0, 0x05, 0x8b, 0xca, 0x28, + 0x81, 0xb7, 0x9b, 0x10, 0xe8, 0xa8, 0x01, 0x08, 0x20, 0x61, 0x8a, 0xc6, 0x52, 0x6c, + 0xf9, 0x4b, 0x13, 0xd9, 0x75, 0x9f, 0x37, 0x33, 0x93, 0x34, 0xe8, 0xb2, 0xc6, 0xbd, + 0xd1, 0xd0, 0xf5, 0xe2, 0x46, 0x3c, 0xff, 0x2b, 0x8d, 0xa6, 0xd2, 0xc6, 0x86, 0xaa, + 0x98, 0x7c, 0xd1, 0xf0, 0x7e, 0x9a, 0xa2, 0x60, 0xdd, 0x04, 0x28, 0xa4, 0xff, 0x78, + 0xaa, 0x8f, 0xda, 0x47, 0x7a, 0xb3, 0x8a, 0xcf, 0xcc, 0xb1, 0x90, 0x91, 0x77, 0xb5, + 0x27, 0xe9, 0x38, 0xf1, 0xf9, 0xdc, 0xf3, 0x1f, 0x4f, 0x40, 0xa9, 0x62, 0x89, 0x51, + 0xfc, 0x2a, 0x7a, 0xbc, 0x04, 0x1e, 0x8c, 0x93, 0x36, 0x08, 0xbb, 0x47, 0xb4, 0x50, + 0xb2, 0x8f, 0xee, 0xe0, 0x41, 0x58, 0xa8, 0x17, 0x4b, 0xff, 0xe4, 0x97, 0x06, 0x02, + 0x48, 0x86, 0x42, 0xc1, 0x9e, 0x61, 0xd4, 0x73, 0xf3, 0xde, 0x0c, 0xb0, 0xb6, 0x4a, + 0x30, 0xd6, 0xf1, 0x46, 0x68, 0xd1, 0xb0, 0x17, 0x77, 0x56, 0x6f, 0xb5, 0xac, 0xc2, + 0xe9, 0x2e, 0x64, 0xd9, 0x75, 0x7f, 0xba, 0x13, 0xc1, 0xee, 0x9c, 0xd0, 0x3a, 0xbe, + 0x98, 0xbd, 0x7e, 0x8a, 0xd7, 0x04, 0x1c, 0x3f, 0xea, 0xe7, 0xc1, 0xa7, 0x24, 0x3a, + 0xe3, 0x61, 0x0a, 0xac, 0x64, 0xfe, 0xc6, 0xc9, 0xfc, 0x94, 0x3d, 0x6a, 0xbc, 0xe9, + 0x10, 0xad, 0xbe, 0x23, 0xb5, 0x46, 0xb4, 0xc2, 0x4a, 0xa9, 0xf2, 0xce, 0x5d, 0x97, + 0x06, 0x2e, 0xe0, 0xd1, 0xcc, 0xc4, 0x8c, 0xfd, 0x1f, 0xdb, 0xa7, 0xfd, 0xac, 0x0b, + 0x04, 0xd1, 0xb3, 0xdc, 0x7a, 0x70, 0x78, 0x1c, 0xdd, 0xa2, 0xa2, 0x70, 0x3d, 0xe0, + 0x03, 0xcd, 0x01, 0x51, 0xec, 0x65, 0xbf, 0x7d, 0x1a, 0xc6, 0x3b, 0xb7, 0x35, 0xbc, + 0x2b, 0xb6, 0x7a, 0xd2, 0xb0, 0x1e, 0xd6, 0xb9, 0xae, 0x2e, 0xbb, 0xd3, 0x7a, 0x8f, + 0x8e, 0xc1, 0xa6, 0x53, 0xa8, 0x7e, ], ock: [ - 0x28, 0xcf, 0x3b, 0xea, 0xc3, 0xbd, 0xe2, 0xe9, 0x63, 0xaa, 0x60, 0x91, 0x3f, 0x10, - 0x5d, 0x25, 0x67, 0xcd, 0xaf, 0xbb, 0x66, 0x09, 0x08, 0x5a, 0x84, 0x3f, 0x75, 0x68, - 0xe4, 0x92, 0xd4, 0x4e, + 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, + 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, + 0x04, 0xa7, 0x8c, 0x0b, ], op: [ 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, - 0x01, 0x70, 0x89, 0x1a, 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, - 0x59, 0xa1, 0x33, 0xf3, 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, - 0xdd, 0x63, 0xe0, 0x62, 0x83, 0x05, 0x47, 0x08, + 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, + 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, + 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, ], c_out: [ - 0x0b, 0x2c, 0xc0, 0xa2, 0x2d, 0x06, 0xfc, 0x36, 0xa0, 0x8a, 0x7d, 0x82, 0x33, 0x8d, - 0x4a, 0xd0, 0x95, 0xa3, 0x93, 0xa1, 0xc2, 0x4a, 0x78, 0x8d, 0x45, 0x24, 0x35, 0x94, - 0x4a, 0xcc, 0xe6, 0x38, 0x1e, 0xcc, 0x69, 0x37, 0xf2, 0xc3, 0x8c, 0x89, 0xa5, 0xf5, - 0x1a, 0xa6, 0x0c, 0xa6, 0x58, 0xfe, 0x71, 0x37, 0x1c, 0x2a, 0x83, 0xf4, 0x96, 0xca, - 0x2e, 0x62, 0x49, 0x79, 0x2e, 0x09, 0xeb, 0x79, 0xea, 0x3a, 0x13, 0x80, 0x32, 0x18, - 0xff, 0x20, 0x88, 0x9d, 0x8c, 0x59, 0xc8, 0x5e, 0x90, 0x99, + 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, + 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, + 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, + 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, + 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, + 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, ], }, TestVector { @@ -1978,34 +1978,34 @@ pub(crate) fn test_vectors() -> Vec { 0x71, 0x55, 0x00, 0xb5, ], nf_old: [ - 0x3b, 0x37, 0x96, 0x78, 0x0c, 0x0a, 0xec, 0x14, 0xed, 0x28, 0x74, 0xb5, 0x23, 0x06, - 0xe1, 0xc3, 0xd5, 0xde, 0x45, 0x93, 0xc6, 0x69, 0xaf, 0x1c, 0xaf, 0x11, 0xbc, 0xb4, - 0xd3, 0x5c, 0x60, 0x12, + 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, + 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, + 0xa3, 0x18, 0x53, 0x3e, ], cmx: [ - 0x4d, 0xa9, 0xdf, 0xdc, 0x70, 0x8c, 0xe8, 0xa0, 0x77, 0xa0, 0x6e, 0xc0, 0x67, 0x79, - 0x24, 0xcf, 0x37, 0x70, 0xed, 0xc2, 0x07, 0xfd, 0x5e, 0x7d, 0x69, 0x5f, 0x71, 0xb0, - 0x15, 0xbb, 0x03, 0x05, + 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, + 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, + 0x51, 0x5b, 0x97, 0x1c, ], esk: [ - 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, 0x52, 0x6d, 0x66, 0x54, - 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, 0xfb, 0xee, 0x5d, 0xe3, - 0x99, 0xca, 0x31, 0x26, + 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, + 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, + 0x46, 0x1e, 0xec, 0x29, ], ephemeral_key: [ - 0x2d, 0xa0, 0x59, 0x4c, 0xd8, 0x74, 0x91, 0x46, 0x52, 0x67, 0xe7, 0x2c, 0x61, 0x89, - 0x07, 0x91, 0xfe, 0xb4, 0x25, 0xa2, 0xbb, 0xcd, 0xda, 0xcf, 0xe4, 0x5a, 0x66, 0x62, - 0x2f, 0x49, 0xef, 0x35, + 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, + 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, + 0x97, 0xf3, 0x23, 0x1c, ], shared_secret: [ - 0xe0, 0xb1, 0x52, 0x67, 0xfd, 0x21, 0x08, 0xeb, 0xbd, 0xd4, 0x16, 0x3f, 0x83, 0xad, - 0xef, 0xb6, 0x1c, 0x3e, 0xdf, 0x56, 0x6d, 0x94, 0x6f, 0xa1, 0xc1, 0x5e, 0x96, 0x46, - 0x43, 0xb1, 0x9c, 0x8e, + 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, + 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, + 0x2b, 0xa0, 0x63, 0x08, ], k_enc: [ - 0x28, 0x48, 0xae, 0x53, 0xaa, 0xce, 0xbe, 0x7c, 0xab, 0x58, 0x73, 0x1d, 0xc2, 0x21, - 0x88, 0x1b, 0x60, 0x2c, 0xc5, 0xa5, 0x3b, 0xcc, 0x1f, 0x76, 0xc8, 0x20, 0xb0, 0xea, - 0x13, 0x55, 0x68, 0x8e, + 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, + 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, + 0x2a, 0x20, 0x47, 0x0b, ], p_enc: [ 0x02, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, @@ -2051,68 +2051,68 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0xc6, 0x38, 0xbf, ], c_enc: [ - 0xf1, 0x42, 0xc4, 0xe5, 0x0e, 0xef, 0x2c, 0x64, 0x44, 0xcc, 0xd4, 0x0b, 0x8c, 0x99, - 0xe5, 0x6a, 0x72, 0xec, 0x4e, 0x30, 0xcf, 0x73, 0x68, 0x75, 0xf0, 0xaa, 0x6b, 0x8e, - 0x6d, 0x9c, 0xc3, 0x67, 0x73, 0x2d, 0xbc, 0x9a, 0xf0, 0xb3, 0x7d, 0x1f, 0xca, 0x6d, - 0x5b, 0xdd, 0x1d, 0xc1, 0x23, 0x79, 0x29, 0x66, 0x99, 0x9d, 0x62, 0xea, 0xf8, 0xc5, - 0xfe, 0x8d, 0x99, 0x91, 0x84, 0xf2, 0x8b, 0x99, 0xec, 0xef, 0xcc, 0x8f, 0x14, 0x8d, - 0xbd, 0x52, 0x02, 0x6f, 0xdb, 0x48, 0xdf, 0xda, 0x7b, 0xad, 0xb6, 0xd1, 0xfc, 0xd2, - 0x9a, 0xd2, 0x19, 0xea, 0xbf, 0xbb, 0x44, 0x3f, 0x5d, 0x0f, 0x98, 0xb6, 0x6a, 0x3a, - 0x25, 0x73, 0x1b, 0x52, 0xd7, 0xf2, 0xdf, 0x70, 0x01, 0x4b, 0x4a, 0xc6, 0x99, 0x34, - 0x32, 0xf8, 0x98, 0x1e, 0x9c, 0xbf, 0xe1, 0x69, 0x13, 0xf6, 0x8a, 0x93, 0x5d, 0x2d, - 0xd0, 0x06, 0xd4, 0x28, 0xf1, 0x45, 0x53, 0xe7, 0x29, 0x86, 0xc7, 0x0f, 0xb4, 0x43, - 0x18, 0xd2, 0x7c, 0x4d, 0x6f, 0x6f, 0xd3, 0x92, 0x3a, 0xb0, 0xf6, 0x28, 0x9a, 0x02, - 0x48, 0x5e, 0x87, 0x17, 0xe5, 0x7d, 0xa0, 0x24, 0xeb, 0xe1, 0x6e, 0x9c, 0xf8, 0x35, - 0xcf, 0x53, 0xd2, 0x19, 0x4f, 0xd4, 0x25, 0x50, 0x06, 0xb8, 0x1b, 0xfd, 0x51, 0xd1, - 0xef, 0x5a, 0xe9, 0xf9, 0xef, 0x6a, 0xf6, 0x57, 0x41, 0x81, 0xe2, 0xe2, 0x26, 0x50, - 0xcb, 0x91, 0x2a, 0x6b, 0x89, 0x88, 0xa0, 0x28, 0x86, 0x32, 0xbc, 0x73, 0x62, 0xbb, - 0xe1, 0x87, 0x23, 0xd8, 0x27, 0xf7, 0x94, 0x58, 0x62, 0x26, 0x0d, 0xf7, 0x8e, 0x95, - 0xd7, 0xd5, 0xe3, 0x31, 0x3f, 0x5a, 0xff, 0x72, 0xe2, 0x1c, 0xe2, 0xdf, 0x00, 0xee, - 0x7e, 0x81, 0x5a, 0xba, 0x17, 0xcc, 0xde, 0x15, 0xc2, 0x7e, 0xee, 0x08, 0x5f, 0x52, - 0xf3, 0x6c, 0x02, 0xec, 0xd6, 0x6c, 0xe1, 0x8b, 0x40, 0x15, 0xbe, 0xb6, 0x09, 0x23, - 0x3f, 0x6e, 0xb2, 0x8e, 0x4a, 0xd5, 0xcd, 0xbe, 0x6f, 0xdc, 0xab, 0x68, 0xbf, 0xbb, - 0x6f, 0xfd, 0x87, 0xd3, 0x86, 0xd8, 0x7e, 0xb1, 0xfe, 0x00, 0x34, 0x27, 0x0f, 0x41, - 0x27, 0x1e, 0xa0, 0x1f, 0x9e, 0xae, 0xa9, 0xe8, 0x9f, 0x78, 0x35, 0x9e, 0x41, 0x73, - 0x94, 0xbb, 0x9d, 0xf5, 0xb6, 0x1c, 0x36, 0xe3, 0x0b, 0xc1, 0xce, 0x4a, 0xb1, 0xbd, - 0xd7, 0x9f, 0xa4, 0x08, 0x3e, 0x82, 0x8d, 0xd1, 0x04, 0xe4, 0x73, 0x80, 0xcd, 0x83, - 0xcd, 0x65, 0x9d, 0xf4, 0x4d, 0xb9, 0x43, 0xdc, 0x07, 0xbc, 0xc8, 0x07, 0x05, 0x04, - 0xa1, 0xc6, 0x55, 0x23, 0x02, 0xe7, 0x4b, 0xe4, 0xb9, 0xc4, 0x32, 0x75, 0xec, 0xc2, - 0x88, 0xce, 0xda, 0x41, 0x59, 0xa9, 0xcc, 0x55, 0x7c, 0x18, 0x19, 0x5c, 0xec, 0x92, - 0x62, 0x24, 0xd8, 0xd6, 0x9e, 0x98, 0xe1, 0x83, 0x5a, 0x2e, 0x29, 0x05, 0x63, 0xef, - 0x20, 0xd0, 0x83, 0xd1, 0x4e, 0x93, 0xcc, 0x1f, 0x3f, 0x76, 0x3e, 0xf5, 0x58, 0x0e, - 0x13, 0x5f, 0xae, 0x1b, 0xb8, 0x54, 0x4a, 0x0c, 0x5c, 0x6d, 0x88, 0x17, 0x41, 0xe4, - 0x51, 0x34, 0x47, 0xac, 0xeb, 0x09, 0x33, 0xe6, 0xeb, 0xaf, 0x0c, 0xe3, 0x13, 0xc1, - 0x8c, 0x9a, 0xf9, 0x5b, 0xa5, 0x61, 0x31, 0xf7, 0x8f, 0x42, 0x72, 0x41, 0x22, 0x65, - 0xbc, 0xf4, 0xc5, 0xf6, 0x80, 0x89, 0x3c, 0xcd, 0xa5, 0x73, 0x7d, 0xa8, 0x23, 0xb7, - 0x63, 0x6e, 0x98, 0xdb, 0xa5, 0x62, 0x44, 0xf2, 0xb9, 0x6a, 0x10, 0x90, 0xa6, 0x60, - 0x38, 0x15, 0xc0, 0xef, 0x54, 0x97, 0x50, 0xf2, 0x47, 0x06, 0x19, 0x0b, 0x55, 0x76, - 0x6e, 0x8a, 0x62, 0x09, 0xa1, 0xc2, 0x2f, 0x67, 0xe8, 0x77, 0x62, 0x66, 0xb6, 0xfa, - 0xe4, 0x5b, 0xf7, 0x94, 0x90, 0x7f, 0x64, 0x71, 0x4f, 0xbe, 0x26, 0xc3, 0x0a, 0xc4, - 0x04, 0x11, 0xf5, 0xe6, 0x4f, 0xc1, 0x66, 0xc8, 0x4f, 0x28, 0xb8, 0x23, 0xfd, 0xaa, - 0x68, 0x32, 0xa3, 0x25, 0x63, 0x31, 0x7d, 0x25, 0x4c, 0x53, 0x16, 0x9b, 0x9f, 0xfb, - 0x24, 0x53, 0xa1, 0x12, 0x2f, 0xa4, 0x4c, 0x7f, 0x17, 0xc1, 0x36, 0xb5, 0x7e, 0x20, - 0xad, 0x17, 0x7a, 0x7e, 0xee, 0xbf, 0x9f, 0x56, 0xfb, 0x0b, 0x55, 0xcc, 0xcf, 0x68, - 0x2b, 0x8a, 0x5b, 0xd8, 0xa7, 0x45, + 0x7b, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, + 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, + 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, + 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0x4a, 0x8c, 0xa9, 0xeb, + 0xfc, 0xe7, 0xf4, 0xfc, 0xec, 0x27, 0xe6, 0x05, 0x8e, 0x44, 0x68, 0xc1, 0x50, 0x10, + 0xd0, 0x17, 0xcb, 0x90, 0x1a, 0xbf, 0xb2, 0x2e, 0xad, 0x86, 0x99, 0x83, 0xf6, 0x9a, + 0xed, 0xf2, 0xda, 0x7d, 0x6a, 0xaf, 0xd1, 0x30, 0x6e, 0xe7, 0x36, 0xf2, 0xdb, 0x33, + 0xbc, 0xe4, 0xb0, 0x9f, 0xca, 0x74, 0x69, 0x2a, 0x52, 0x09, 0xa7, 0x39, 0x2b, 0x7e, + 0xa9, 0x68, 0x5b, 0xe9, 0xec, 0x43, 0x1f, 0xfe, 0x50, 0xf7, 0x0f, 0x90, 0x22, 0x74, + 0x05, 0x03, 0x45, 0x2a, 0xb5, 0x14, 0x92, 0xb1, 0xf7, 0x47, 0x7e, 0xda, 0x42, 0x7b, + 0x42, 0x3a, 0x93, 0x1b, 0x26, 0x38, 0x6c, 0x56, 0xe4, 0x27, 0x86, 0x3d, 0x46, 0xb1, + 0x99, 0xff, 0xa0, 0x8c, 0x52, 0x9f, 0xa5, 0x72, 0x1f, 0x68, 0xe9, 0x14, 0xf6, 0xea, + 0x6a, 0x8a, 0xe6, 0xae, 0xcb, 0xf7, 0x37, 0x47, 0x1e, 0xbd, 0x83, 0xdb, 0xa9, 0xa7, + 0xcd, 0x89, 0x75, 0x66, 0x20, 0x4e, 0x2b, 0xae, 0x63, 0xe3, 0x4e, 0x70, 0x32, 0x51, + 0x02, 0x96, 0x92, 0x0d, 0x7e, 0x7a, 0x7c, 0xcf, 0x0f, 0xeb, 0xe7, 0xa8, 0x33, 0x69, + 0x6a, 0x4b, 0x67, 0x41, 0x88, 0x5e, 0x9b, 0x94, 0x0c, 0x61, 0xdd, 0x8d, 0x44, 0x38, + 0x54, 0x74, 0x15, 0x31, 0x0b, 0x15, 0xcf, 0x18, 0xdc, 0x19, 0x90, 0x07, 0x8c, 0x70, + 0x8b, 0xea, 0xc3, 0x32, 0xa8, 0xe0, 0x81, 0x46, 0xa6, 0x95, 0x8e, 0xa6, 0xf4, 0x3f, + 0xd0, 0xc2, 0xc8, 0xe9, 0x99, 0xaa, 0x4f, 0xdf, 0x1e, 0x77, 0xef, 0xde, 0x54, 0xfd, + 0x65, 0xc6, 0x7a, 0x3f, 0x07, 0xda, 0xf5, 0xf6, 0x04, 0x49, 0x60, 0xa0, 0xb6, 0xdd, + 0x84, 0x1f, 0xf8, 0xb8, 0xa5, 0x92, 0xc7, 0xb1, 0x09, 0x34, 0x2c, 0x73, 0x5c, 0x2a, + 0x0e, 0x37, 0xb3, 0x0b, 0x8b, 0xaa, 0x5c, 0x77, 0x01, 0xeb, 0xc7, 0xa8, 0xf8, 0x20, + 0xc0, 0x22, 0x7c, 0xa5, 0x00, 0x3f, 0x36, 0xee, 0x68, 0xf7, 0xb2, 0x89, 0x81, 0xc2, + 0x73, 0x32, 0x03, 0x9d, 0xd6, 0xa4, 0x94, 0xf0, 0xcd, 0x02, 0xbd, 0xd2, 0x8f, 0x68, + 0x3e, 0xca, 0x1b, 0x03, 0x2a, 0xfc, 0x09, 0xdd, 0x0c, 0xd8, 0x56, 0xcb, 0xc1, 0xa3, + 0x5e, 0x74, 0xd4, 0x0c, 0x24, 0x53, 0xdf, 0xe2, 0x42, 0xc8, 0x6a, 0x7a, 0x60, 0xbc, + 0xbd, 0xdb, 0x17, 0x96, 0x6c, 0x7d, 0xba, 0x76, 0x9e, 0xab, 0xd1, 0xc1, 0x67, 0xb7, + 0xe8, 0x19, 0x78, 0xf9, 0x12, 0x8b, 0xac, 0x26, 0xa2, 0x8d, 0x77, 0x21, 0x30, 0x79, + 0xcb, 0x56, 0xc0, 0x95, 0xa7, 0xc0, 0x60, 0xde, 0x0e, 0x77, 0x5c, 0xa8, 0xac, 0x8e, + 0x6c, 0xa9, 0x4d, 0x19, 0xc6, 0x16, 0x2e, 0x44, 0xf7, 0xa8, 0xf0, 0x14, 0x9d, 0x31, + 0xd3, 0x46, 0x3d, 0x01, 0xb6, 0x1a, 0x14, 0x63, 0xa9, 0xde, 0x3d, 0x8a, 0xb7, 0x40, + 0x04, 0x0a, 0x76, 0xe0, 0x5b, 0x37, 0x64, 0x28, 0x86, 0x29, 0x87, 0x59, 0x5b, 0x87, + 0xce, 0xa6, 0x94, 0xfe, 0x92, 0x0a, 0x06, 0x7e, 0x81, 0x6b, 0x4f, 0x29, 0xa3, 0xa2, + 0x24, 0x50, 0x14, 0x0f, 0x13, 0x5d, 0x71, 0x9a, 0x97, 0x1b, 0x81, 0xfc, 0x19, 0x16, + 0x98, 0x0a, 0x55, 0xdd, 0xf8, 0xd9, 0x87, 0x30, 0x57, 0x36, 0x35, 0xa0, 0x70, 0x85, + 0xc4, 0xe7, 0x7c, 0x7e, 0x1c, 0xdb, 0xb6, 0x85, 0x42, 0x6e, 0xe4, 0x62, 0xcc, 0x30, + 0x83, 0xa3, 0xf5, 0xa3, 0xb9, 0x17, 0xc0, 0x6f, 0x9a, 0x96, 0xf9, 0xf7, 0xbd, 0x81, + 0xac, 0xa4, 0x9b, 0xef, 0x95, 0xb9, 0x28, 0x06, 0xc4, 0x2d, 0x09, 0x12, 0x01, 0x31, + 0x42, 0xb2, 0x2a, 0x7b, 0xad, 0x72, 0x12, 0x11, 0x46, 0x91, 0xf1, 0xdc, 0x72, 0x64, + 0xc6, 0x7e, 0x76, 0x34, 0xf5, 0xd7, 0x95, 0xc9, 0x75, 0x30, 0x62, 0xe3, 0x06, 0xc0, + 0x6b, 0xc1, 0x03, 0xaa, 0x01, 0xc1, 0x0d, 0x1f, 0x5d, 0xd4, 0xcd, 0x59, 0xf6, 0x53, + 0x2c, 0xb7, 0x23, 0xe3, 0xa0, 0x26, ], ock: [ - 0x06, 0x3c, 0x83, 0xa4, 0x95, 0x74, 0xe7, 0x80, 0x35, 0x89, 0xcc, 0x3d, 0x34, 0xb4, - 0x38, 0x90, 0xf3, 0xd7, 0x63, 0x87, 0x35, 0xe7, 0xbd, 0x5e, 0xbd, 0xd1, 0xa5, 0xea, - 0xb9, 0xd9, 0xc5, 0xd6, + 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, + 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, + 0x8b, 0xb3, 0x29, 0x3d, ], op: [ 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, - 0x44, 0x6d, 0xf4, 0x39, 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, - 0x52, 0x6d, 0x66, 0x54, 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, - 0xfb, 0xee, 0x5d, 0xe3, 0x99, 0xca, 0x31, 0x26, + 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, + 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, + 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, ], c_out: [ - 0xca, 0xb7, 0x8d, 0xd1, 0x83, 0xf3, 0xe1, 0x6a, 0xf7, 0x6e, 0x9a, 0x90, 0x3d, 0xd4, - 0x2a, 0x96, 0x67, 0xbf, 0xe7, 0x08, 0xce, 0x88, 0x79, 0xb8, 0x38, 0x6e, 0x62, 0xac, - 0x9f, 0x66, 0x74, 0xf4, 0x93, 0x59, 0x5d, 0xa5, 0x06, 0xe9, 0xef, 0x06, 0xbb, 0xa2, - 0x4a, 0x93, 0x80, 0x60, 0xe5, 0xd3, 0x82, 0xcc, 0x75, 0xdf, 0xab, 0x97, 0xe0, 0xf8, - 0x49, 0x4b, 0x47, 0x6a, 0xdf, 0x4f, 0xfd, 0x96, 0xff, 0x7f, 0x1b, 0x4f, 0x16, 0xf8, - 0x59, 0x4b, 0x7c, 0x5a, 0x21, 0x9c, 0x7a, 0x00, 0xad, 0x15, + 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, + 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, + 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, + 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, + 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, + 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, ], }, ] diff --git a/src/test_vectors/note_encryption_zsa.rs b/src/test_vectors/note_encryption_zsa.rs new file mode 100644 index 000000000..534e24407 --- /dev/null +++ b/src/test_vectors/note_encryption_zsa.rs @@ -0,0 +1,4389 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_note_encryption) + +pub(crate) struct TestVector { + pub(crate) incoming_viewing_key: [u8; 64], + pub(crate) ovk: [u8; 32], + pub(crate) default_d: [u8; 11], + pub(crate) default_pk_d: [u8; 32], + pub(crate) v: u64, + pub(crate) rseed: [u8; 32], + pub(crate) asset: [u8; 32], + pub(crate) memo: [u8; 512], + pub(crate) cv_net: [u8; 32], + pub(crate) nf_old: [u8; 32], + pub(crate) cmx: [u8; 32], + pub(crate) esk: [u8; 32], + pub(crate) ephemeral_key: [u8; 32], + pub(crate) shared_secret: [u8; 32], + pub(crate) k_enc: [u8; 32], + pub(crate) p_enc: [u8; 596], + pub(crate) c_enc: [u8; 612], + pub(crate) ock: [u8; 32], + pub(crate) op: [u8; 64], + pub(crate) c_out: [u8; 80], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + incoming_viewing_key: [ + 0x10, 0x39, 0xd8, 0xe6, 0x4a, 0x80, 0x90, 0x2e, 0x10, 0x59, 0x47, 0x81, 0x7d, 0xf3, + 0xbd, 0xfb, 0x7d, 0xf7, 0x03, 0x0e, 0x68, 0x73, 0x9f, 0x9c, 0x53, 0x3a, 0x36, 0xbf, + 0x5a, 0x6a, 0x80, 0x72, 0x43, 0x10, 0x6d, 0xe9, 0xa7, 0xec, 0x54, 0xdd, 0x36, 0xdf, + 0xa7, 0x0b, 0xdb, 0xd9, 0x07, 0x2d, 0xbd, 0xda, 0xb5, 0xe0, 0x66, 0xaa, 0xef, 0xfc, + 0xf9, 0xbb, 0xa3, 0x20, 0xd4, 0xff, 0xf7, 0x12, + ], + ovk: [ + 0x5d, 0x7a, 0x8f, 0x73, 0x9a, 0x2d, 0x9e, 0x94, 0x5b, 0x0c, 0xe1, 0x52, 0xa8, 0x04, + 0x9e, 0x29, 0x4c, 0x4d, 0x6e, 0x66, 0xb1, 0x64, 0x93, 0x9d, 0xaf, 0xfa, 0x2e, 0xf6, + 0xee, 0x69, 0x21, 0x48, + ], + default_d: [ + 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, + ], + default_pk_d: [ + 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, + 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, + 0x49, 0x50, 0x69, 0x2c, + ], + v: 8567075990963576717, + rseed: [ + 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, + 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, + 0x30, 0xa7, 0x35, 0x94, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, + 0x25, 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, + 0x91, 0x2a, 0x63, 0x81, 0xce, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, + 0xd7, 0x55, 0x1d, 0xb5, 0xfd, 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, + 0xd4, 0x77, 0x08, 0x37, 0x56, 0xd5, 0x9a, 0xf8, 0x0d, 0x06, 0xa7, 0x45, 0xf4, 0x4a, + 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, + 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, + 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, 0xc2, + 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, 0x94, + 0x90, 0x3d, 0x3c, 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, + 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, + 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, + 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, + 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, + 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, 0x13, 0x09, 0x13, + 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, 0xe1, + 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, + 0xa9, 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, + 0xda, 0xe6, 0x9c, 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, + 0x93, 0x1d, 0xe5, 0x18, 0x85, 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, + 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, + 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, 0xe5, 0x3e, 0x29, 0xfe, 0xf2, + 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, + 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, + 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, + 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, + 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, + 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, + 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, + 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, 0xed, 0x42, 0x43, 0x5e, 0x92, 0x47, 0x69, + 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, 0x7b, 0x89, 0xe0, + 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, 0xf2, 0x65, 0x72, + 0x50, 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, + 0xbc, 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, + 0xe7, 0x1a, 0x02, 0xaf, 0x11, 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, + 0xb1, 0xfc, 0xe4, 0x67, 0x50, 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, + 0xc3, 0x82, 0x85, 0x7d, 0xee, 0xcc, 0x40, 0xa9, + ], + cv_net: [ + 0xdd, 0xba, 0x24, 0xf3, 0x9f, 0x70, 0x8e, 0xd7, 0xa7, 0x48, 0x57, 0x13, 0x71, 0x11, + 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, + 0xc1, 0x3e, 0x71, 0x01, + ], + nf_old: [ + 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, + 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, + 0x05, 0xee, 0xf3, 0x27, + ], + cmx: [ + 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, + 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, + 0xf1, 0x7b, 0xd9, 0x21, + ], + esk: [ + 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, + 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, + 0xff, 0xf1, 0xbd, 0x1a, + ], + ephemeral_key: [ + 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, + 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, + 0xf5, 0xec, 0x45, 0x17, + ], + shared_secret: [ + 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, + 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, + 0x21, 0x50, 0x48, 0xa5, + ], + k_enc: [ + 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, + 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, + 0x79, 0x18, 0x03, 0x20, + ], + p_enc: [ + 0x03, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, + 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, + 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, + 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, 0x30, 0xa7, 0x35, 0x94, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, + 0x25, 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, + 0x91, 0x2a, 0x63, 0x81, 0xce, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, + 0xd7, 0x55, 0x1d, 0xb5, 0xfd, 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, + 0xd4, 0x77, 0x08, 0x37, 0x56, 0xd5, 0x9a, 0xf8, 0x0d, 0x06, 0xa7, 0x45, 0xf4, 0x4a, + 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, + 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, + 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, 0xc2, + 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, 0x94, + 0x90, 0x3d, 0x3c, 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, + 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, + 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, + 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, + 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, + 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, 0x13, 0x09, 0x13, + 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, 0xe1, + 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, + 0xa9, 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, + 0xda, 0xe6, 0x9c, 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, + 0x93, 0x1d, 0xe5, 0x18, 0x85, 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, + 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, + 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, 0xe5, 0x3e, 0x29, 0xfe, 0xf2, + 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, + 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, + 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, + 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, + 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, + 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, + 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, + 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, 0xed, 0x42, 0x43, 0x5e, 0x92, 0x47, 0x69, + 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, 0x7b, 0x89, 0xe0, + 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, 0xf2, 0x65, 0x72, + 0x50, 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, + 0xbc, 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, + 0xe7, 0x1a, 0x02, 0xaf, 0x11, 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, + 0xb1, 0xfc, 0xe4, 0x67, 0x50, 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, + 0xc3, 0x82, 0x85, 0x7d, 0xee, 0xcc, 0x40, 0xa9, + ], + c_enc: [ + 0x92, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, + 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, + 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, + 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0xe1, 0x06, 0x21, 0xb8, + 0x97, 0xe9, 0x79, 0x10, 0xba, 0xa5, 0x63, 0xd0, 0xb4, 0xc3, 0x8f, 0x87, 0x77, 0xf9, + 0xdf, 0xb5, 0x5a, 0x4d, 0x0c, 0xa6, 0x49, 0x80, 0x7a, 0x6e, 0x7e, 0x3b, 0x63, 0x7b, + 0xe7, 0x83, 0x5c, 0x0c, 0x07, 0x6e, 0x6f, 0x06, 0xee, 0x5c, 0x8a, 0xac, 0x6a, 0xd2, + 0x13, 0x00, 0xf8, 0xe1, 0xcd, 0x39, 0x5f, 0x69, 0x2d, 0xc5, 0x72, 0xab, 0x07, 0xfd, + 0x4b, 0xe1, 0xf2, 0xc6, 0x52, 0x09, 0x64, 0xed, 0xec, 0x3b, 0xe5, 0x56, 0x22, 0xac, + 0x4d, 0x23, 0x85, 0x8c, 0x39, 0x8d, 0xf6, 0x6d, 0x6a, 0x6e, 0x54, 0x60, 0x18, 0xf9, + 0x81, 0x66, 0x89, 0x24, 0xbe, 0x96, 0x3b, 0x7c, 0xbb, 0x0c, 0x7f, 0x10, 0x4d, 0x16, + 0x07, 0xfb, 0xcb, 0xc0, 0x18, 0x49, 0xd9, 0x93, 0x72, 0xcb, 0x8e, 0x64, 0xb2, 0xca, + 0x15, 0xd7, 0xf8, 0xc5, 0x37, 0x20, 0x05, 0xa8, 0x89, 0xd6, 0xa9, 0x31, 0x23, 0x59, + 0x42, 0x09, 0xe4, 0xd2, 0x59, 0x7b, 0x6e, 0x83, 0x78, 0x2e, 0x5d, 0x1a, 0xb0, 0xc5, + 0xd6, 0x42, 0xbe, 0x32, 0xe7, 0xb4, 0x89, 0x85, 0xaa, 0x07, 0x7e, 0x9a, 0x76, 0xbd, + 0xe2, 0x7d, 0xf4, 0x26, 0x74, 0x8b, 0xf3, 0x25, 0x52, 0x01, 0x56, 0x88, 0xb3, 0x6e, + 0x34, 0xff, 0x9d, 0x22, 0x11, 0xd8, 0x72, 0xfb, 0x23, 0x6a, 0x18, 0x2f, 0xe4, 0xf2, + 0x87, 0xa5, 0x5b, 0xfc, 0xee, 0xa3, 0xed, 0x99, 0xfd, 0xc2, 0x91, 0xf9, 0x1d, 0x6e, + 0xf8, 0xd2, 0x9a, 0x27, 0x8f, 0xa6, 0x46, 0xe8, 0xe7, 0xdc, 0x66, 0xd4, 0x9b, 0x38, + 0x62, 0x26, 0x7e, 0xd5, 0x8b, 0x31, 0x66, 0x09, 0x97, 0xa5, 0x8f, 0x29, 0x73, 0x5c, + 0xc6, 0xe5, 0x98, 0x65, 0x54, 0x2f, 0x5d, 0x90, 0x8c, 0xe5, 0x2d, 0x9f, 0x5b, 0x29, + 0xc9, 0x78, 0x24, 0xd1, 0x4d, 0x4d, 0x64, 0xcd, 0xbe, 0x56, 0x93, 0xb5, 0x1b, 0x7e, + 0xc7, 0x31, 0xc9, 0x92, 0x4b, 0x4f, 0x47, 0x5a, 0x14, 0xd0, 0x58, 0x7b, 0xe6, 0x45, + 0x44, 0x8a, 0x07, 0x55, 0x4f, 0x15, 0xbc, 0x9d, 0xaf, 0xa1, 0xf7, 0x38, 0x6a, 0xe8, + 0x6f, 0x71, 0x48, 0x2b, 0x35, 0x6e, 0xa7, 0x9c, 0xdc, 0x44, 0x73, 0x2c, 0xfa, 0x41, + 0x46, 0xe6, 0xca, 0x51, 0x04, 0xf0, 0xa4, 0x60, 0x7b, 0xd6, 0x4b, 0x58, 0x39, 0x6e, + 0x44, 0x3f, 0xad, 0x2c, 0xfc, 0x36, 0xdd, 0xd3, 0xae, 0x9a, 0xa4, 0xbe, 0xa8, 0x7a, + 0xde, 0xd5, 0xec, 0x35, 0x17, 0x42, 0xfc, 0x5a, 0x90, 0x6a, 0xd0, 0x54, 0xd3, 0x59, + 0x43, 0x16, 0xcc, 0x54, 0xb8, 0x74, 0xbb, 0xce, 0xc2, 0xa8, 0x14, 0x31, 0x50, 0x18, + 0xbc, 0x7e, 0x1d, 0x3c, 0x74, 0x84, 0x72, 0xbd, 0x96, 0x77, 0x76, 0x5d, 0xcf, 0x59, + 0xb1, 0x6d, 0x55, 0xa3, 0xf1, 0x86, 0x4f, 0x75, 0x1a, 0x69, 0x3d, 0x76, 0x9c, 0xc7, + 0x6b, 0x8e, 0x32, 0x8a, 0x9a, 0xc8, 0x3b, 0xe1, 0x78, 0x39, 0x1b, 0xeb, 0x5f, 0x28, + 0xab, 0x69, 0x2b, 0x6f, 0x02, 0xa3, 0xf7, 0x49, 0x8a, 0x4b, 0xc5, 0x51, 0xf8, 0x48, + 0x7d, 0xae, 0xba, 0x3b, 0xe0, 0x2e, 0xb0, 0x20, 0xc1, 0x60, 0xf8, 0x78, 0x53, 0x91, + 0xaa, 0x03, 0xde, 0x44, 0x7b, 0x37, 0xf9, 0x5b, 0xec, 0xfe, 0x3e, 0xca, 0x95, 0xae, + 0x62, 0xab, 0xa0, 0x82, 0x20, 0xee, 0x87, 0xd2, 0x48, 0x16, 0xb0, 0x99, 0x5f, 0x27, + 0x30, 0xe8, 0xff, 0x9a, 0xca, 0x21, 0x8b, 0x88, 0xe3, 0x1b, 0x1f, 0xb7, 0x78, 0x3a, + 0x29, 0x80, 0xf7, 0xb2, 0x98, 0x44, 0xc1, 0x06, 0x26, 0xa2, 0x13, 0xa9, 0x81, 0x41, + 0x7d, 0x90, 0xdf, 0xf9, 0xfb, 0x2a, 0xba, 0xfe, 0xc8, 0x38, 0x23, 0x0e, 0x1a, 0x55, + 0xcf, 0xc5, 0xf7, 0xf8, 0x19, 0xab, 0xf6, 0xe5, 0xb0, 0xa7, 0x48, 0x3b, 0xf1, 0xbc, + 0xeb, 0x15, 0xe8, 0x5b, 0xfe, 0x12, 0xfd, 0x55, 0x02, 0x81, 0xe5, 0x28, 0x20, 0xd0, + 0xbd, 0xb2, 0xa5, 0xba, 0x34, 0xe3, 0x74, 0xca, 0x2f, 0xfd, 0xac, 0x56, 0xce, 0x51, + 0x3c, 0xf3, 0xdd, 0x23, 0xde, 0x9f, 0xb4, 0xa1, 0xd2, 0xff, 0x4f, 0xfe, 0x74, 0x9b, + 0xd8, 0xcb, 0x30, 0x8f, 0x9a, 0xf7, 0xb6, 0xfe, 0xa2, 0x39, + ], + ock: [ + 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, + 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, + 0xc6, 0x6a, 0x1a, 0xd6, + ], + op: [ + 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, + 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, + 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, + 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, + 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, + ], + c_out: [ + 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, + 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, + 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, + 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, + 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, + 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xfd, 0x9e, 0x9a, 0x1f, 0x38, 0x1c, 0xbe, 0x75, 0xcd, 0x8d, 0x6a, 0xe1, 0x2f, 0xca, + 0x87, 0x2e, 0x94, 0x00, 0xf0, 0x02, 0x72, 0xb0, 0x29, 0x65, 0x2e, 0x65, 0x6c, 0x8f, + 0x3c, 0x4b, 0xf0, 0x37, 0xee, 0xef, 0x96, 0x42, 0x1b, 0x2f, 0xab, 0x2f, 0xb3, 0xad, + 0x1e, 0x0a, 0xd8, 0x50, 0x2d, 0x74, 0xe6, 0xf0, 0x8f, 0x0d, 0xd5, 0x18, 0xf8, 0xfa, + 0x82, 0x2a, 0x65, 0xbe, 0x27, 0x40, 0xc0, 0x21, + ], + ovk: [ + 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, 0xa0, + 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, 0x82, 0x84, 0x2d, 0x38, 0x25, + 0xb3, 0xd6, 0xda, 0x05, + ], + default_d: [ + 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, + ], + default_pk_d: [ + 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, + 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, + 0x4a, 0xd7, 0xc7, 0x84, + ], + v: 9072946746592546880, + rseed: [ + 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, 0x14, 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, + 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, 0x77, 0xe3, 0x1b, 0xa4, 0x59, 0xb4, + 0x4e, 0x30, 0x77, 0x68, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, + 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, + 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, + 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, + 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, + 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, + 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, 0xfa, 0xa7, + 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, + 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, + 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, + 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, + 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, + 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, + 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, + 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, + 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, + 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, + 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, + 0x1c, 0xe7, 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, + 0xe7, 0x5e, 0xf8, 0xe3, 0xf8, 0xbd, 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, + 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, + 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, 0x0a, 0x88, 0x06, 0x12, 0x53, 0xca, 0x28, 0x5b, + 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, + 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, + 0xff, 0xa0, 0x05, 0xc3, 0x12, 0x24, 0x1c, 0x2d, 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, + 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, + 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, 0x41, 0x87, 0x2c, 0xfc, + 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, 0xf9, 0x30, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, 0xc4, 0xa3, 0xe1, 0x03, 0xf6, 0x01, 0x10, 0xa1, 0x6b, 0x13, + 0x37, 0x12, 0x97, 0x04, 0xbf, 0x47, 0x54, 0xff, 0x6b, 0xa9, 0xfb, 0xe6, 0x59, 0x51, + 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, + 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, + ], + cv_net: [ + 0x15, 0x49, 0x70, 0x7e, 0x1e, 0xd2, 0xb2, 0xeb, 0x66, 0x15, 0x65, 0x0b, 0xec, 0x45, + 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, + 0x25, 0x7a, 0xd8, 0xb3, + ], + nf_old: [ + 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, + 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, + 0x4d, 0xb2, 0xc7, 0x31, + ], + cmx: [ + 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, + 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, + 0xc5, 0xe9, 0xf9, 0x0f, + ], + esk: [ + 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, + 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, + 0xbd, 0xc9, 0xce, 0x14, + ], + ephemeral_key: [ + 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, + 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, + 0x31, 0x69, 0x85, 0x8c, + ], + shared_secret: [ + 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, + 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, + 0x68, 0x7e, 0xd9, 0xb0, + ], + k_enc: [ + 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, + 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, + 0x58, 0x6a, 0xc0, 0xd9, + ], + p_enc: [ + 0x03, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, + 0xaf, 0xd8, 0xfe, 0x94, 0xe9, 0x7d, 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, 0x14, + 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, + 0x77, 0xe3, 0x1b, 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, + 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, + 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, + 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, + 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, + 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, + 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, 0xfa, 0xa7, + 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, + 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, + 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, + 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, + 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, + 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, + 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, + 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, + 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, + 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, + 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, + 0x1c, 0xe7, 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, + 0xe7, 0x5e, 0xf8, 0xe3, 0xf8, 0xbd, 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, + 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, + 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, 0x0a, 0x88, 0x06, 0x12, 0x53, 0xca, 0x28, 0x5b, + 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, + 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, + 0xff, 0xa0, 0x05, 0xc3, 0x12, 0x24, 0x1c, 0x2d, 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, + 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, + 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, 0x41, 0x87, 0x2c, 0xfc, + 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, 0xf9, 0x30, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, 0xc4, 0xa3, 0xe1, 0x03, 0xf6, 0x01, 0x10, 0xa1, 0x6b, 0x13, + 0x37, 0x12, 0x97, 0x04, 0xbf, 0x47, 0x54, 0xff, 0x6b, 0xa9, 0xfb, 0xe6, 0x59, 0x51, + 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, + 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, + ], + c_enc: [ + 0x1a, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, + 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, + 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, + 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0x22, 0x57, 0x7c, 0x40, + 0x9d, 0xa2, 0xdc, 0xa2, 0xef, 0xc2, 0xb3, 0xf8, 0x86, 0x97, 0xf5, 0xed, 0x20, 0x5a, + 0xb2, 0xf9, 0xea, 0x29, 0x85, 0xdd, 0x8b, 0x91, 0xb3, 0x2c, 0x1d, 0x7a, 0x8d, 0xa3, + 0xe8, 0x60, 0x57, 0xe8, 0x70, 0x8c, 0x7e, 0xb1, 0x32, 0x32, 0xaf, 0x56, 0x5d, 0xa5, + 0xa3, 0x5d, 0xe5, 0x06, 0x26, 0x29, 0x6a, 0xa6, 0x07, 0x1a, 0xa0, 0x0a, 0x2c, 0xf2, + 0x47, 0x3f, 0xa8, 0x0b, 0xfd, 0xbb, 0x95, 0x89, 0x48, 0x2a, 0x83, 0x5d, 0x56, 0xd2, + 0x27, 0xe6, 0x29, 0xe3, 0x5b, 0x2f, 0xb0, 0xf3, 0xdd, 0x38, 0xf1, 0x3b, 0xaa, 0x24, + 0xe5, 0x88, 0x26, 0x66, 0x25, 0x31, 0x07, 0x6a, 0xab, 0x9f, 0x4e, 0x3d, 0xe2, 0xc0, + 0xd0, 0x03, 0xe8, 0xd1, 0x0a, 0x8a, 0x70, 0x64, 0x3f, 0xe2, 0x4b, 0x1e, 0x4a, 0x2b, + 0x6d, 0x42, 0x74, 0xbc, 0xc5, 0xfc, 0xe0, 0x49, 0x3a, 0xec, 0x37, 0xe3, 0x24, 0xe9, + 0xb5, 0x13, 0x47, 0xe3, 0x20, 0xa8, 0xa0, 0x0d, 0xd6, 0xd6, 0xcd, 0x3a, 0x46, 0x70, + 0x4b, 0x90, 0xaf, 0x0d, 0x30, 0xe1, 0xda, 0x33, 0x7a, 0x2a, 0x82, 0x98, 0x26, 0xce, + 0x70, 0xf4, 0xf8, 0xa7, 0xcd, 0x31, 0x37, 0x59, 0x42, 0xda, 0x53, 0x4b, 0x68, 0x8b, + 0xf0, 0xbe, 0x8b, 0x6b, 0x90, 0x52, 0x6b, 0x18, 0x1d, 0x9f, 0x07, 0x2f, 0x60, 0x83, + 0x42, 0xb2, 0x4c, 0x89, 0xda, 0xd7, 0xf7, 0xf3, 0x07, 0x9f, 0xe9, 0x9b, 0x6c, 0xfc, + 0x73, 0x38, 0xc2, 0x86, 0x94, 0x2c, 0xab, 0x60, 0x72, 0x95, 0x3f, 0x08, 0x6d, 0x59, + 0xa1, 0xd6, 0x60, 0x00, 0xa4, 0xea, 0x6a, 0xe6, 0x3f, 0xbb, 0xfc, 0x5d, 0xc7, 0x6e, + 0x23, 0x14, 0x29, 0x88, 0x72, 0x5d, 0xea, 0x47, 0x43, 0x52, 0x2b, 0x92, 0x2c, 0xeb, + 0x89, 0xf1, 0x94, 0x8c, 0xe9, 0x43, 0xd5, 0x73, 0x66, 0x10, 0x30, 0xfe, 0x0c, 0xec, + 0x60, 0x7b, 0xd2, 0x47, 0xc9, 0xb5, 0x91, 0x84, 0x3d, 0x3e, 0x38, 0xa9, 0x47, 0x29, + 0x29, 0x8e, 0x60, 0x05, 0xdf, 0xd9, 0xf4, 0xf0, 0xf4, 0x86, 0xcb, 0xa7, 0xb6, 0x51, + 0xd5, 0xb9, 0xd3, 0xd7, 0xae, 0x64, 0x48, 0xe3, 0x9d, 0x19, 0xd7, 0x77, 0x41, 0x79, + 0x2d, 0x60, 0x9c, 0x2e, 0xb9, 0x7f, 0xa9, 0xba, 0x6e, 0x0b, 0x33, 0xdf, 0x17, 0xff, + 0x0f, 0x3c, 0x61, 0x16, 0x38, 0x9f, 0x3d, 0xa3, 0xb0, 0xd6, 0x56, 0xb9, 0x15, 0x3e, + 0xb3, 0x3f, 0x1b, 0xb5, 0x03, 0x94, 0xd7, 0x37, 0xb6, 0x78, 0x15, 0x35, 0xe9, 0x2b, + 0xcc, 0x8a, 0x7e, 0x56, 0xe6, 0x08, 0x02, 0x33, 0x3f, 0xea, 0x10, 0xde, 0xb6, 0xc7, + 0x9b, 0x66, 0x3d, 0xdd, 0x92, 0x82, 0x84, 0x91, 0x46, 0x23, 0x3f, 0x07, 0x8a, 0xbb, + 0x6d, 0x38, 0xec, 0x80, 0x7c, 0x45, 0x79, 0x4d, 0xf4, 0xaa, 0xfe, 0xe8, 0xd7, 0x58, + 0xb9, 0xda, 0xb4, 0xf3, 0x9a, 0xbd, 0x9a, 0xce, 0x42, 0xea, 0x39, 0x88, 0x9d, 0x5f, + 0x40, 0x24, 0x12, 0x24, 0xa9, 0xe1, 0x17, 0x1b, 0xad, 0xcf, 0x4c, 0x5a, 0x75, 0x9e, + 0x3b, 0xb9, 0xc7, 0x9e, 0x3d, 0x1c, 0x72, 0xb4, 0xaf, 0x65, 0x81, 0xe0, 0x7b, 0xde, + 0xdf, 0xc1, 0x7f, 0xe6, 0x82, 0x70, 0x79, 0x9c, 0x3b, 0xb0, 0x8b, 0x11, 0xfe, 0xfe, + 0xb1, 0xed, 0xb2, 0xbb, 0xa0, 0xf1, 0x14, 0x6b, 0x54, 0x01, 0x2a, 0xd3, 0x17, 0x57, + 0x10, 0x2c, 0xaa, 0x5d, 0xee, 0x1f, 0xcf, 0x1f, 0x97, 0x13, 0x34, 0x0d, 0xa2, 0x52, + 0xbd, 0x41, 0xed, 0x4a, 0xe2, 0x11, 0xf3, 0x5f, 0x88, 0x99, 0x1e, 0x1f, 0xe3, 0x47, + 0xd7, 0x0f, 0x52, 0xcd, 0x12, 0xd7, 0x36, 0x13, 0xcd, 0x13, 0xcf, 0xb1, 0x2e, 0xb2, + 0x5f, 0x83, 0x2b, 0x34, 0xc8, 0xb6, 0x69, 0x3a, 0x85, 0xb4, 0x00, 0xfc, 0xe3, 0x03, + 0xdc, 0xcb, 0x3f, 0x8d, 0x90, 0xf5, 0xb7, 0x0c, 0x1e, 0x00, 0xd1, 0xb5, 0x41, 0xe0, + 0xe1, 0x37, 0x3c, 0xc0, 0xc4, 0x05, 0x00, 0x72, 0x18, 0x76, 0x90, 0xf1, 0x38, 0xfd, + 0x25, 0x03, 0x27, 0x2a, 0x3f, 0x9e, 0xc5, 0x72, 0x0d, 0xd3, 0xe5, 0xb1, 0xda, 0x59, + 0x51, 0x4d, 0x4c, 0xb5, 0x0b, 0x1a, 0x44, 0x5a, 0x9d, 0x66, + ], + ock: [ + 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, + 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, + 0x09, 0xd0, 0x15, 0xac, + ], + op: [ + 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, + 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, + 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, + 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, + 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, + ], + c_out: [ + 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, + 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, + 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, + 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, + 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, + 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x91, 0xee, 0x20, 0x54, 0x48, 0xc9, 0x8b, 0x69, 0xa3, 0x3e, 0xbf, 0x29, 0x35, 0x09, + 0x5d, 0x79, 0xc2, 0x53, 0x02, 0x9e, 0x5e, 0x5d, 0xc0, 0x2d, 0xf5, 0x8a, 0x10, 0x03, + 0xd1, 0xd8, 0x5c, 0x27, 0xf2, 0xde, 0xf5, 0xb1, 0x10, 0xfd, 0x43, 0xd7, 0x15, 0xe8, + 0xd5, 0x9e, 0xc4, 0xad, 0x0f, 0x41, 0x02, 0x0e, 0xc6, 0x60, 0xcd, 0x97, 0x33, 0xe7, + 0x79, 0xb5, 0x1a, 0x7a, 0xc2, 0xd5, 0xa6, 0x31, + ], + ovk: [ + 0x18, 0x2f, 0x20, 0x7b, 0x31, 0x75, 0x96, 0x1f, 0x64, 0x11, 0xa4, 0x93, 0xbf, 0xfd, + 0x04, 0x8e, 0x7d, 0x0d, 0x87, 0xd8, 0x2f, 0xe6, 0xf9, 0x90, 0xa2, 0xb0, 0xa2, 0x5f, + 0x5a, 0xa0, 0x11, 0x1a, + ], + default_d: [ + 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, + ], + default_pk_d: [ + 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, + 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, + 0x15, 0x37, 0x14, 0x0d, + ], + v: 14400879385556610631, + rseed: [ + 0xd5, 0x07, 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, + 0x00, 0xfb, 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, + 0xbf, 0xee, 0x76, 0xaf, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x61, 0x66, 0x81, 0x90, 0xbd, 0x52, 0xed, 0x49, 0x0e, 0x67, 0x7b, 0x51, 0x5d, + 0x01, 0x43, 0x84, 0xaf, 0x07, 0x21, 0x9c, 0x7c, 0x0e, 0xe7, 0xfc, 0x7b, 0xfc, 0x79, + 0xf3, 0x25, 0x64, 0x4e, 0x4d, 0xf4, 0xc0, 0xd7, 0xdb, 0x08, 0xe9, 0xf0, 0xbd, 0x02, + 0x49, 0x43, 0xc7, 0x05, 0xab, 0xff, 0x89, 0x94, 0xbf, 0xa6, 0x05, 0xcf, 0xbc, 0x7e, + 0xd7, 0x46, 0xa7, 0xd3, 0xf7, 0xc3, 0x7d, 0x9e, 0x8b, 0xdc, 0x43, 0x3b, 0x7d, 0x79, + 0xe0, 0x8a, 0x12, 0xf7, 0x38, 0xa8, 0xf0, 0xdb, 0xdd, 0xfe, 0xf2, 0xf2, 0x65, 0x7e, + 0xf3, 0xe4, 0x7d, 0x1b, 0x0f, 0xd1, 0x1e, 0x6a, 0x13, 0x31, 0x1f, 0xb7, 0x99, 0xc7, + 0x9c, 0x64, 0x1d, 0x9d, 0xa4, 0x3b, 0x33, 0xe7, 0xad, 0x01, 0x2e, 0x28, 0x25, 0x53, + 0x98, 0x78, 0x92, 0x62, 0x27, 0x5f, 0x11, 0x75, 0xbe, 0x84, 0x62, 0xc0, 0x14, 0x91, + 0xc4, 0xd8, 0x42, 0x40, 0x6d, 0x0e, 0xc4, 0x28, 0x2c, 0x95, 0x26, 0x17, 0x4a, 0x09, + 0x87, 0x8f, 0xe8, 0xfd, 0xde, 0x33, 0xa2, 0x96, 0x04, 0xe5, 0xe5, 0xe7, 0xb2, 0xa0, + 0x25, 0xd6, 0x65, 0x0b, 0x97, 0xdb, 0xb5, 0x2b, 0xef, 0xb5, 0x9b, 0x1d, 0x30, 0xa5, + 0x74, 0x33, 0xb0, 0xa3, 0x51, 0x47, 0x44, 0x44, 0x09, 0x9d, 0xaa, 0x37, 0x10, 0x46, + 0x61, 0x32, 0x60, 0xcf, 0x33, 0x54, 0xcf, 0xcd, 0xad, 0xa6, 0x63, 0xec, 0xe8, 0x24, + 0xff, 0xd7, 0xe4, 0x43, 0x93, 0x88, 0x6a, 0x86, 0x16, 0x5d, 0xdd, 0xdf, 0x2b, 0x4c, + 0x41, 0x77, 0x35, 0x54, 0xc8, 0x69, 0x95, 0x26, 0x94, 0x08, 0xb1, 0x1e, 0x67, 0x37, + 0xa4, 0xc4, 0x47, 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, + 0xbc, 0x00, 0x0a, 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, + 0x66, 0x94, 0x13, 0xf8, 0x38, 0x79, 0x33, 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, + 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, + 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, 0xaf, 0x71, 0xb8, 0x9f, 0x90, 0x3f, 0x5d, + 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, 0x4d, 0x63, 0x59, + 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, 0x6c, 0x4a, 0x2f, + 0xbe, 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, + 0x90, 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, + 0x46, 0x06, 0xc9, 0xcf, 0x9f, 0x3d, 0xd3, 0x3e, 0x57, 0x6f, 0x05, 0xcd, 0x1d, 0xd6, + 0x81, 0x1c, 0x62, 0x98, 0x75, 0x7d, 0x77, 0xd9, 0xe8, 0x10, 0xab, 0xdb, 0x22, 0x6a, + 0xfc, 0xaa, 0x43, 0x46, 0xa6, 0x56, 0x0f, 0x89, 0x32, 0xb3, 0x18, 0x1f, 0xd3, 0x55, + 0xd5, 0xd3, 0x91, 0x97, 0x61, 0x83, 0xf8, 0xd9, 0x93, 0x88, 0x83, 0x96, 0x32, 0xd6, + 0x35, 0x4f, 0x66, 0x6d, 0x09, 0xd3, 0xe5, 0x62, 0x9e, 0xa1, 0x97, 0x37, 0x38, 0x86, + 0x13, 0xd3, 0x8a, 0x34, 0xfd, 0x0f, 0x6e, 0x50, 0xee, 0x5a, 0x0c, 0xc9, 0x67, 0x71, + 0x77, 0xf5, 0x00, 0x28, 0xc1, 0x41, 0x37, 0x81, 0x87, 0xbd, 0x28, 0x19, 0x40, 0x3f, + 0xc5, 0x34, 0xf8, 0x00, 0x76, 0xe9, 0x38, 0x0c, 0xb4, 0x96, 0x4d, 0x3b, 0x6b, 0x45, + 0x81, 0x9d, 0x3b, 0x8e, 0x9c, 0xaf, 0x54, 0xf0, 0x51, 0x85, 0x2d, 0x67, 0x1b, 0xf8, + 0xc1, 0xff, 0xde, 0x2d, 0x15, 0x10, 0x75, 0x64, 0x18, 0xcb, 0x48, 0x10, 0x93, 0x6a, + 0xa5, 0x7e, 0x69, 0x65, 0xd6, 0xfb, 0x65, 0x6a, 0x76, 0x0b, 0x7f, 0x19, 0xad, 0xf9, + 0x6c, 0x17, 0x34, 0x88, 0x55, 0x21, 0x93, 0xb1, + ], + cv_net: [ + 0xc3, 0x94, 0x68, 0x5d, 0x92, 0x95, 0x59, 0x7e, 0x21, 0x55, 0x7f, 0x21, 0x9f, 0x3c, + 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, + 0xc5, 0xb3, 0x73, 0x3e, + ], + nf_old: [ + 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, + 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, + 0x25, 0xb9, 0xff, 0x16, + ], + cmx: [ + 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, + 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, + 0xe0, 0x24, 0x69, 0x05, + ], + esk: [ + 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, + 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, + 0x59, 0xe0, 0x4c, 0x3a, + ], + ephemeral_key: [ + 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, + 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, + 0x86, 0x6b, 0xce, 0x23, + ], + shared_secret: [ + 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, + 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, + 0xe2, 0x62, 0xd3, 0xb6, + ], + k_enc: [ + 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, + 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, + 0x0c, 0xdd, 0x5a, 0xa6, + ], + p_enc: [ + 0x03, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, + 0x58, 0x85, 0x80, 0x33, 0xda, 0xc7, 0xd5, 0x07, 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, + 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, 0x00, 0xfb, 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, + 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, 0xbf, 0xee, 0x76, 0xaf, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x61, 0x66, 0x81, 0x90, 0xbd, 0x52, 0xed, 0x49, 0x0e, 0x67, 0x7b, 0x51, 0x5d, + 0x01, 0x43, 0x84, 0xaf, 0x07, 0x21, 0x9c, 0x7c, 0x0e, 0xe7, 0xfc, 0x7b, 0xfc, 0x79, + 0xf3, 0x25, 0x64, 0x4e, 0x4d, 0xf4, 0xc0, 0xd7, 0xdb, 0x08, 0xe9, 0xf0, 0xbd, 0x02, + 0x49, 0x43, 0xc7, 0x05, 0xab, 0xff, 0x89, 0x94, 0xbf, 0xa6, 0x05, 0xcf, 0xbc, 0x7e, + 0xd7, 0x46, 0xa7, 0xd3, 0xf7, 0xc3, 0x7d, 0x9e, 0x8b, 0xdc, 0x43, 0x3b, 0x7d, 0x79, + 0xe0, 0x8a, 0x12, 0xf7, 0x38, 0xa8, 0xf0, 0xdb, 0xdd, 0xfe, 0xf2, 0xf2, 0x65, 0x7e, + 0xf3, 0xe4, 0x7d, 0x1b, 0x0f, 0xd1, 0x1e, 0x6a, 0x13, 0x31, 0x1f, 0xb7, 0x99, 0xc7, + 0x9c, 0x64, 0x1d, 0x9d, 0xa4, 0x3b, 0x33, 0xe7, 0xad, 0x01, 0x2e, 0x28, 0x25, 0x53, + 0x98, 0x78, 0x92, 0x62, 0x27, 0x5f, 0x11, 0x75, 0xbe, 0x84, 0x62, 0xc0, 0x14, 0x91, + 0xc4, 0xd8, 0x42, 0x40, 0x6d, 0x0e, 0xc4, 0x28, 0x2c, 0x95, 0x26, 0x17, 0x4a, 0x09, + 0x87, 0x8f, 0xe8, 0xfd, 0xde, 0x33, 0xa2, 0x96, 0x04, 0xe5, 0xe5, 0xe7, 0xb2, 0xa0, + 0x25, 0xd6, 0x65, 0x0b, 0x97, 0xdb, 0xb5, 0x2b, 0xef, 0xb5, 0x9b, 0x1d, 0x30, 0xa5, + 0x74, 0x33, 0xb0, 0xa3, 0x51, 0x47, 0x44, 0x44, 0x09, 0x9d, 0xaa, 0x37, 0x10, 0x46, + 0x61, 0x32, 0x60, 0xcf, 0x33, 0x54, 0xcf, 0xcd, 0xad, 0xa6, 0x63, 0xec, 0xe8, 0x24, + 0xff, 0xd7, 0xe4, 0x43, 0x93, 0x88, 0x6a, 0x86, 0x16, 0x5d, 0xdd, 0xdf, 0x2b, 0x4c, + 0x41, 0x77, 0x35, 0x54, 0xc8, 0x69, 0x95, 0x26, 0x94, 0x08, 0xb1, 0x1e, 0x67, 0x37, + 0xa4, 0xc4, 0x47, 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, + 0xbc, 0x00, 0x0a, 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, + 0x66, 0x94, 0x13, 0xf8, 0x38, 0x79, 0x33, 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, + 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, + 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, 0xaf, 0x71, 0xb8, 0x9f, 0x90, 0x3f, 0x5d, + 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, 0x4d, 0x63, 0x59, + 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, 0x6c, 0x4a, 0x2f, + 0xbe, 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, + 0x90, 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, + 0x46, 0x06, 0xc9, 0xcf, 0x9f, 0x3d, 0xd3, 0x3e, 0x57, 0x6f, 0x05, 0xcd, 0x1d, 0xd6, + 0x81, 0x1c, 0x62, 0x98, 0x75, 0x7d, 0x77, 0xd9, 0xe8, 0x10, 0xab, 0xdb, 0x22, 0x6a, + 0xfc, 0xaa, 0x43, 0x46, 0xa6, 0x56, 0x0f, 0x89, 0x32, 0xb3, 0x18, 0x1f, 0xd3, 0x55, + 0xd5, 0xd3, 0x91, 0x97, 0x61, 0x83, 0xf8, 0xd9, 0x93, 0x88, 0x83, 0x96, 0x32, 0xd6, + 0x35, 0x4f, 0x66, 0x6d, 0x09, 0xd3, 0xe5, 0x62, 0x9e, 0xa1, 0x97, 0x37, 0x38, 0x86, + 0x13, 0xd3, 0x8a, 0x34, 0xfd, 0x0f, 0x6e, 0x50, 0xee, 0x5a, 0x0c, 0xc9, 0x67, 0x71, + 0x77, 0xf5, 0x00, 0x28, 0xc1, 0x41, 0x37, 0x81, 0x87, 0xbd, 0x28, 0x19, 0x40, 0x3f, + 0xc5, 0x34, 0xf8, 0x00, 0x76, 0xe9, 0x38, 0x0c, 0xb4, 0x96, 0x4d, 0x3b, 0x6b, 0x45, + 0x81, 0x9d, 0x3b, 0x8e, 0x9c, 0xaf, 0x54, 0xf0, 0x51, 0x85, 0x2d, 0x67, 0x1b, 0xf8, + 0xc1, 0xff, 0xde, 0x2d, 0x15, 0x10, 0x75, 0x64, 0x18, 0xcb, 0x48, 0x10, 0x93, 0x6a, + 0xa5, 0x7e, 0x69, 0x65, 0xd6, 0xfb, 0x65, 0x6a, 0x76, 0x0b, 0x7f, 0x19, 0xad, 0xf9, + 0x6c, 0x17, 0x34, 0x88, 0x55, 0x21, 0x93, 0xb1, + ], + c_enc: [ + 0x80, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, + 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, + 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, + 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0x3c, 0xf5, 0x82, 0xa1, + 0x4f, 0x08, 0xfc, 0xa9, 0xb3, 0x7a, 0xac, 0x85, 0x1f, 0xf9, 0xf5, 0x80, 0x5c, 0x57, + 0x74, 0x8a, 0x3f, 0xe8, 0x1b, 0x88, 0xc9, 0x8c, 0x96, 0xfd, 0x2a, 0x75, 0xc4, 0xf6, + 0x66, 0xb6, 0x1d, 0x20, 0x74, 0x06, 0x5c, 0xf4, 0x4a, 0x30, 0xa1, 0x98, 0xa2, 0x98, + 0xb7, 0xda, 0x42, 0x7c, 0x18, 0x60, 0x8a, 0x8f, 0x13, 0x83, 0x63, 0xf0, 0x55, 0x40, + 0x42, 0xd3, 0xe3, 0xa7, 0xe3, 0x22, 0x94, 0x51, 0x51, 0xc6, 0x3b, 0xb2, 0x37, 0xb3, + 0x20, 0xbc, 0x78, 0x0a, 0x8f, 0x9e, 0x01, 0xc6, 0x01, 0xf0, 0x34, 0xbc, 0xf0, 0x37, + 0x67, 0xd5, 0xd7, 0x50, 0x40, 0x2a, 0x23, 0x80, 0x0f, 0x46, 0xec, 0x08, 0x78, 0x0a, + 0x8f, 0x78, 0xe9, 0xa2, 0x37, 0xa9, 0xcb, 0x83, 0x06, 0x26, 0x1d, 0x1b, 0xb4, 0xc3, + 0xf6, 0x2e, 0xf4, 0xcb, 0x0f, 0x70, 0x34, 0x65, 0x32, 0x24, 0xfe, 0x77, 0x17, 0x9a, + 0x4d, 0x12, 0x15, 0x9a, 0x87, 0x66, 0xff, 0xc5, 0x9b, 0xee, 0x68, 0xd9, 0x74, 0xd2, + 0x27, 0x73, 0xe5, 0xca, 0x4f, 0x34, 0xf4, 0x62, 0x73, 0xa4, 0x46, 0x33, 0x69, 0xb1, + 0x76, 0xa6, 0x1f, 0x1e, 0x47, 0x8c, 0x2d, 0x3c, 0x4e, 0x42, 0x70, 0x13, 0xe5, 0xd8, + 0x69, 0x75, 0xea, 0x91, 0x93, 0x05, 0x0e, 0x52, 0xa7, 0x02, 0x6f, 0x76, 0x96, 0x4c, + 0xa0, 0x18, 0x15, 0x9b, 0xdc, 0x19, 0x6c, 0x44, 0xca, 0xd2, 0xd2, 0x62, 0x3d, 0x33, + 0x50, 0x7e, 0xf0, 0xfe, 0xc1, 0x0f, 0x9d, 0x80, 0xb2, 0x08, 0xe3, 0xc3, 0x3f, 0x7d, + 0x50, 0x76, 0x41, 0x63, 0xb3, 0xf0, 0x33, 0x29, 0xad, 0x41, 0xeb, 0x5a, 0x4f, 0xb4, + 0xf3, 0xab, 0x8e, 0xef, 0x2d, 0xa5, 0xcb, 0x3a, 0x7c, 0x86, 0x22, 0x16, 0x48, 0x70, + 0xa8, 0x2c, 0x63, 0x5d, 0x23, 0x51, 0x53, 0x9b, 0x97, 0x3c, 0x40, 0xd5, 0x8e, 0x91, + 0x79, 0x43, 0x6b, 0x9c, 0x0b, 0x74, 0xfd, 0x5e, 0xab, 0x81, 0x49, 0x59, 0xd2, 0x80, + 0xea, 0x3f, 0x8e, 0x09, 0xd8, 0x44, 0x2f, 0xea, 0x4a, 0xdc, 0x8c, 0xc9, 0xc2, 0xfe, + 0x50, 0xef, 0xad, 0x2e, 0xe1, 0x9a, 0xb5, 0x85, 0x7a, 0x2d, 0x2f, 0xb1, 0xd1, 0x13, + 0x67, 0x08, 0x22, 0xb9, 0x57, 0x95, 0xa3, 0x4d, 0x20, 0xf7, 0xc6, 0x37, 0xf8, 0xdc, + 0xcf, 0xe7, 0x35, 0x52, 0xfd, 0x34, 0x17, 0x6a, 0xbf, 0x0f, 0x8e, 0x3c, 0xfa, 0x70, + 0xbe, 0xc8, 0x84, 0x4b, 0x87, 0xb1, 0x44, 0xcb, 0x99, 0xb0, 0xb0, 0x9b, 0x47, 0xc6, + 0x62, 0xdd, 0x70, 0x5e, 0x4d, 0x74, 0xc1, 0x5d, 0x47, 0x42, 0x98, 0x33, 0xe7, 0x80, + 0x5d, 0x88, 0x40, 0x46, 0xc0, 0xd9, 0x36, 0xc8, 0x72, 0x32, 0xcd, 0xc9, 0x53, 0xbf, + 0x6e, 0x61, 0x93, 0xb4, 0xcf, 0x67, 0x81, 0x12, 0x8e, 0xbe, 0x7a, 0x51, 0xdb, 0x9b, + 0x36, 0x67, 0x38, 0x08, 0xad, 0x77, 0x18, 0xe2, 0x50, 0xcb, 0x51, 0x15, 0x85, 0xf6, + 0xbc, 0x09, 0x78, 0xbd, 0x17, 0xe4, 0x71, 0x7e, 0xa4, 0x19, 0x3d, 0x09, 0x5d, 0x22, + 0x2b, 0xa1, 0xb2, 0xf9, 0xd8, 0x18, 0x98, 0x1d, 0xf1, 0x72, 0xa4, 0x91, 0xd8, 0x41, + 0xbc, 0x73, 0xec, 0x17, 0x93, 0x41, 0xa2, 0x8f, 0x03, 0x8a, 0xa3, 0xe4, 0xc8, 0x65, + 0x24, 0x11, 0xf1, 0x85, 0xa6, 0x49, 0x92, 0xa6, 0xce, 0xa6, 0xc4, 0x5c, 0x70, 0xe9, + 0xd6, 0x64, 0x69, 0x4b, 0xc9, 0x44, 0x1f, 0x29, 0xc4, 0x81, 0x81, 0x5a, 0x82, 0xb3, + 0xa3, 0x30, 0xc9, 0x6c, 0x05, 0xfc, 0x9c, 0x48, 0x5a, 0xe8, 0xd9, 0x96, 0xb6, 0xf9, + 0xf6, 0x87, 0xf3, 0x90, 0x1f, 0x74, 0x0a, 0xc8, 0x9a, 0xb2, 0x42, 0xf2, 0xaa, 0x0c, + 0xe7, 0xb0, 0xeb, 0x14, 0xb4, 0x2d, 0x65, 0xba, 0xd9, 0xfe, 0x5c, 0xe2, 0x91, 0xa2, + 0x2c, 0xb1, 0xff, 0xdf, 0xdf, 0x27, 0x30, 0xd6, 0x8f, 0x68, 0x2d, 0xe0, 0xf9, 0xf3, + 0xa3, 0x04, 0xf5, 0x0c, 0x4f, 0xfd, 0xf9, 0x58, 0x30, 0x6c, 0x11, 0xa2, 0x91, 0x70, + 0xdd, 0xae, 0x90, 0x65, 0xcc, 0xc9, 0xd4, 0xd2, 0x77, 0x62, 0x6e, 0x78, 0x81, 0x72, + 0x3a, 0xe1, 0x72, 0xff, 0x09, 0xdb, 0x09, 0x38, 0x6f, 0x9e, + ], + ock: [ + 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, + 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, + 0xfa, 0x2e, 0xfd, 0xe8, + ], + op: [ + 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, + 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, + 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, + 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, + 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, + ], + c_out: [ + 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, + 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, + 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, + 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, + 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, + 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xf1, 0x90, 0x42, 0xb9, 0xd1, 0x0c, 0xc4, 0x80, 0xa0, 0x8c, 0x04, 0x32, 0x2d, 0xb6, + 0xec, 0x4e, 0x41, 0x2e, 0xaa, 0x84, 0xc9, 0x71, 0x82, 0x8c, 0xcc, 0xd7, 0x33, 0xa1, + 0x1f, 0x25, 0x3e, 0xda, 0x8a, 0xc3, 0x0b, 0xa3, 0x1f, 0xbc, 0x89, 0x5d, 0x60, 0xb9, + 0x83, 0x06, 0x2a, 0x5f, 0x45, 0x33, 0x90, 0x79, 0x32, 0x26, 0xff, 0xd9, 0x21, 0xbd, + 0x64, 0xac, 0x39, 0x07, 0x03, 0x85, 0x6a, 0x0b, + ], + ovk: [ + 0xda, 0xdc, 0x96, 0x6c, 0x8a, 0x54, 0x66, 0xb6, 0x1f, 0xc9, 0x98, 0xc3, 0x1f, 0x10, + 0x70, 0xd9, 0xa5, 0xc9, 0xa6, 0xd2, 0x68, 0xd3, 0x04, 0xfe, 0x6b, 0x8f, 0xd3, 0xb4, + 0x01, 0x03, 0x48, 0x61, + ], + default_d: [ + 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, + ], + default_pk_d: [ + 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, + 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, + 0x14, 0x93, 0x16, 0x36, + ], + v: 17936016275122962426, + rseed: [ + 0x49, 0x95, 0x0a, 0xfc, 0xb0, 0xef, 0x46, 0x2a, 0x2a, 0xe0, 0x24, 0xb0, 0xf0, 0x22, + 0x4d, 0xfd, 0x73, 0x68, 0x4b, 0x88, 0xc7, 0xfb, 0xe9, 0x2d, 0x02, 0xb6, 0x8f, 0x75, + 0x9c, 0x47, 0x52, 0x66, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x3c, 0xd7, 0xb9, 0x7a, 0x14, 0x94, 0x36, 0x49, 0x30, 0x55, 0x21, 0x32, 0x6b, + 0xde, 0x08, 0x56, 0x30, 0x86, 0x46, 0x29, 0x29, 0x1b, 0xae, 0x25, 0xff, 0x88, 0x22, + 0xa1, 0x4c, 0x4b, 0x66, 0x6a, 0x92, 0x59, 0xad, 0x0d, 0xc4, 0x2a, 0x82, 0x90, 0xac, + 0x7b, 0xc7, 0xf5, 0x3a, 0x16, 0xf3, 0x79, 0xf7, 0x58, 0xe5, 0xde, 0x75, 0x0f, 0x04, + 0xfd, 0x7c, 0xad, 0x47, 0x70, 0x1c, 0x85, 0x97, 0xf9, 0x78, 0x88, 0xbe, 0xa6, 0xfa, + 0x0b, 0xf2, 0x99, 0x99, 0x56, 0xfb, 0xfd, 0x0e, 0xe6, 0x8e, 0xc3, 0x6e, 0x46, 0x88, + 0x80, 0x9a, 0xe2, 0x31, 0xeb, 0x8b, 0xc4, 0x36, 0x9f, 0x5f, 0xe1, 0x57, 0x3f, 0x57, + 0xe0, 0x99, 0xd9, 0xc0, 0x99, 0x01, 0xbf, 0x39, 0xca, 0xac, 0x48, 0xdc, 0x11, 0x95, + 0x6a, 0x8a, 0xe9, 0x05, 0xea, 0xd8, 0x69, 0x54, 0x54, 0x7c, 0x44, 0x8a, 0xe4, 0x3d, + 0x31, 0x5e, 0x66, 0x9c, 0x42, 0x42, 0xda, 0x56, 0x59, 0x38, 0xf4, 0x17, 0xbf, 0x43, + 0xce, 0x7b, 0x2b, 0x30, 0xb1, 0xcd, 0x40, 0x18, 0x38, 0x8e, 0x1a, 0x91, 0x0f, 0x0f, + 0xc4, 0x1f, 0xb0, 0x87, 0x7a, 0x59, 0x25, 0xe4, 0x66, 0x81, 0x9d, 0x37, 0x5b, 0x0a, + 0x91, 0x2d, 0x4f, 0xe8, 0x43, 0xb7, 0x6e, 0xf6, 0xf2, 0x23, 0xf0, 0xf7, 0xc8, 0x94, + 0xf3, 0x8f, 0x7a, 0xb7, 0x80, 0xdf, 0xd7, 0x5f, 0x66, 0x9c, 0x8c, 0x06, 0xcf, 0xfa, + 0x43, 0xeb, 0x47, 0x56, 0x5a, 0x50, 0xe3, 0xb1, 0xfa, 0x45, 0xad, 0x61, 0xce, 0x9a, + 0x1c, 0x47, 0x27, 0xb7, 0xaa, 0xa5, 0x35, 0x62, 0xf5, 0x23, 0xe7, 0x39, 0x52, 0xbb, + 0xf3, 0x3d, 0x8a, 0x41, 0x04, 0x07, 0x8a, 0xde, 0x3e, 0xaa, 0xa4, 0x96, 0x99, 0xa6, + 0x9f, 0xdf, 0x1c, 0x5a, 0xc7, 0x73, 0x21, 0x46, 0xee, 0x5e, 0x1d, 0x6b, 0x6c, 0xa9, + 0xb9, 0x18, 0x0f, 0x96, 0x4c, 0xc9, 0xd0, 0x87, 0x8a, 0xe1, 0x37, 0x35, 0x24, 0xd7, + 0xd5, 0x10, 0xe5, 0x82, 0x27, 0xdf, 0x6d, 0xe9, 0xd3, 0x0d, 0x27, 0x18, 0x67, 0x64, + 0x01, 0x77, 0xb0, 0xf1, 0x85, 0x6e, 0x28, 0xd5, 0xc8, 0xaf, 0xb0, 0x95, 0xef, 0x61, + 0x84, 0xfe, 0xd6, 0x51, 0x58, 0x90, 0x22, 0xee, 0xae, 0xa4, 0xc0, 0xce, 0x1f, 0xa6, + 0xf0, 0x85, 0x09, 0x2b, 0x04, 0x97, 0x94, 0x89, 0x17, 0x2b, 0x3e, 0xf8, 0x19, 0x4a, + 0x79, 0x8d, 0xf5, 0x72, 0x4d, 0x6b, 0x05, 0xf1, 0xae, 0x00, 0x00, 0x13, 0xa0, 0x8d, + 0x61, 0x2b, 0xca, 0x8a, 0x8c, 0x31, 0x44, 0x3c, 0x10, 0x34, 0x6d, 0xbf, 0x61, 0xde, + 0x84, 0x75, 0xc0, 0xbb, 0xec, 0x51, 0x04, 0xb4, 0x75, 0x56, 0xaf, 0x3d, 0x51, 0x44, + 0x58, 0xe2, 0x32, 0x1d, 0x14, 0x60, 0x71, 0x78, 0x9d, 0x23, 0x35, 0x93, 0x4a, 0x68, + 0x06, 0x14, 0xe8, 0x35, 0x62, 0xf8, 0x2d, 0xfd, 0x40, 0x5b, 0x54, 0xa4, 0x5e, 0xb3, + 0x2c, 0x16, 0x54, 0x48, 0xd4, 0xd5, 0xd6, 0x1c, 0xa2, 0x85, 0x95, 0x85, 0x36, 0x9f, + 0x53, 0xf1, 0xa1, 0x37, 0xe9, 0xe8, 0x2b, 0x67, 0xb8, 0xfd, 0xaf, 0x01, 0xbd, 0xa5, + 0x4a, 0x31, 0x73, 0x11, 0x89, 0x6a, 0xe1, 0x02, 0x80, 0xa0, 0x32, 0x44, 0x0c, 0x42, + 0x0a, 0x42, 0x1e, 0x94, 0x4d, 0x1e, 0x95, 0x2b, 0x70, 0xd5, 0x82, 0x6c, 0xd3, 0xb0, + 0x8b, 0x7d, 0xb9, 0x63, 0x0f, 0xe4, 0xfd, 0x5f, 0x22, 0x12, 0x5d, 0xe8, 0x40, 0xfc, + 0xc4, 0x0b, 0x98, 0x03, 0x8a, 0xf1, 0x1d, 0x55, 0xbe, 0x25, 0x43, 0x25, 0x97, 0xb4, + 0xb6, 0x5b, 0x9e, 0xc1, 0xc7, 0xa8, 0xbb, 0xfd, 0x05, 0x2c, 0xbf, 0x7e, 0x1c, 0x17, + 0x85, 0x31, 0x49, 0x34, 0xb2, 0x62, 0xd5, 0x85, 0x37, 0x54, 0xf1, 0xf1, 0x77, 0x71, + 0xcf, 0xb7, 0x50, 0x30, 0x72, 0x65, 0x57, 0x53, + ], + cv_net: [ + 0xd4, 0x51, 0xb4, 0x62, 0x89, 0xba, 0x99, 0x8c, 0x0c, 0xce, 0xd1, 0xcc, 0x15, 0xb3, + 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, + 0x32, 0xb5, 0x0e, 0x96, + ], + nf_old: [ + 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, + 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, + 0xf5, 0x0e, 0x92, 0x37, + ], + cmx: [ + 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, + 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, + 0xb1, 0x41, 0x41, 0x30, + ], + esk: [ + 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, + 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, + 0xcb, 0x52, 0xa6, 0x13, + ], + ephemeral_key: [ + 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, + 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, + 0x0a, 0x2c, 0x60, 0x98, + ], + shared_secret: [ + 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, + 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, + 0x2f, 0x7b, 0x3b, 0x36, + ], + k_enc: [ + 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, + 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, + 0xdf, 0x21, 0x73, 0x73, + ], + p_enc: [ + 0x03, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, + 0x54, 0xec, 0xc5, 0x87, 0xe9, 0xf8, 0x49, 0x95, 0x0a, 0xfc, 0xb0, 0xef, 0x46, 0x2a, + 0x2a, 0xe0, 0x24, 0xb0, 0xf0, 0x22, 0x4d, 0xfd, 0x73, 0x68, 0x4b, 0x88, 0xc7, 0xfb, + 0xe9, 0x2d, 0x02, 0xb6, 0x8f, 0x75, 0x9c, 0x47, 0x52, 0x66, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x3c, 0xd7, 0xb9, 0x7a, 0x14, 0x94, 0x36, 0x49, 0x30, 0x55, 0x21, 0x32, 0x6b, + 0xde, 0x08, 0x56, 0x30, 0x86, 0x46, 0x29, 0x29, 0x1b, 0xae, 0x25, 0xff, 0x88, 0x22, + 0xa1, 0x4c, 0x4b, 0x66, 0x6a, 0x92, 0x59, 0xad, 0x0d, 0xc4, 0x2a, 0x82, 0x90, 0xac, + 0x7b, 0xc7, 0xf5, 0x3a, 0x16, 0xf3, 0x79, 0xf7, 0x58, 0xe5, 0xde, 0x75, 0x0f, 0x04, + 0xfd, 0x7c, 0xad, 0x47, 0x70, 0x1c, 0x85, 0x97, 0xf9, 0x78, 0x88, 0xbe, 0xa6, 0xfa, + 0x0b, 0xf2, 0x99, 0x99, 0x56, 0xfb, 0xfd, 0x0e, 0xe6, 0x8e, 0xc3, 0x6e, 0x46, 0x88, + 0x80, 0x9a, 0xe2, 0x31, 0xeb, 0x8b, 0xc4, 0x36, 0x9f, 0x5f, 0xe1, 0x57, 0x3f, 0x57, + 0xe0, 0x99, 0xd9, 0xc0, 0x99, 0x01, 0xbf, 0x39, 0xca, 0xac, 0x48, 0xdc, 0x11, 0x95, + 0x6a, 0x8a, 0xe9, 0x05, 0xea, 0xd8, 0x69, 0x54, 0x54, 0x7c, 0x44, 0x8a, 0xe4, 0x3d, + 0x31, 0x5e, 0x66, 0x9c, 0x42, 0x42, 0xda, 0x56, 0x59, 0x38, 0xf4, 0x17, 0xbf, 0x43, + 0xce, 0x7b, 0x2b, 0x30, 0xb1, 0xcd, 0x40, 0x18, 0x38, 0x8e, 0x1a, 0x91, 0x0f, 0x0f, + 0xc4, 0x1f, 0xb0, 0x87, 0x7a, 0x59, 0x25, 0xe4, 0x66, 0x81, 0x9d, 0x37, 0x5b, 0x0a, + 0x91, 0x2d, 0x4f, 0xe8, 0x43, 0xb7, 0x6e, 0xf6, 0xf2, 0x23, 0xf0, 0xf7, 0xc8, 0x94, + 0xf3, 0x8f, 0x7a, 0xb7, 0x80, 0xdf, 0xd7, 0x5f, 0x66, 0x9c, 0x8c, 0x06, 0xcf, 0xfa, + 0x43, 0xeb, 0x47, 0x56, 0x5a, 0x50, 0xe3, 0xb1, 0xfa, 0x45, 0xad, 0x61, 0xce, 0x9a, + 0x1c, 0x47, 0x27, 0xb7, 0xaa, 0xa5, 0x35, 0x62, 0xf5, 0x23, 0xe7, 0x39, 0x52, 0xbb, + 0xf3, 0x3d, 0x8a, 0x41, 0x04, 0x07, 0x8a, 0xde, 0x3e, 0xaa, 0xa4, 0x96, 0x99, 0xa6, + 0x9f, 0xdf, 0x1c, 0x5a, 0xc7, 0x73, 0x21, 0x46, 0xee, 0x5e, 0x1d, 0x6b, 0x6c, 0xa9, + 0xb9, 0x18, 0x0f, 0x96, 0x4c, 0xc9, 0xd0, 0x87, 0x8a, 0xe1, 0x37, 0x35, 0x24, 0xd7, + 0xd5, 0x10, 0xe5, 0x82, 0x27, 0xdf, 0x6d, 0xe9, 0xd3, 0x0d, 0x27, 0x18, 0x67, 0x64, + 0x01, 0x77, 0xb0, 0xf1, 0x85, 0x6e, 0x28, 0xd5, 0xc8, 0xaf, 0xb0, 0x95, 0xef, 0x61, + 0x84, 0xfe, 0xd6, 0x51, 0x58, 0x90, 0x22, 0xee, 0xae, 0xa4, 0xc0, 0xce, 0x1f, 0xa6, + 0xf0, 0x85, 0x09, 0x2b, 0x04, 0x97, 0x94, 0x89, 0x17, 0x2b, 0x3e, 0xf8, 0x19, 0x4a, + 0x79, 0x8d, 0xf5, 0x72, 0x4d, 0x6b, 0x05, 0xf1, 0xae, 0x00, 0x00, 0x13, 0xa0, 0x8d, + 0x61, 0x2b, 0xca, 0x8a, 0x8c, 0x31, 0x44, 0x3c, 0x10, 0x34, 0x6d, 0xbf, 0x61, 0xde, + 0x84, 0x75, 0xc0, 0xbb, 0xec, 0x51, 0x04, 0xb4, 0x75, 0x56, 0xaf, 0x3d, 0x51, 0x44, + 0x58, 0xe2, 0x32, 0x1d, 0x14, 0x60, 0x71, 0x78, 0x9d, 0x23, 0x35, 0x93, 0x4a, 0x68, + 0x06, 0x14, 0xe8, 0x35, 0x62, 0xf8, 0x2d, 0xfd, 0x40, 0x5b, 0x54, 0xa4, 0x5e, 0xb3, + 0x2c, 0x16, 0x54, 0x48, 0xd4, 0xd5, 0xd6, 0x1c, 0xa2, 0x85, 0x95, 0x85, 0x36, 0x9f, + 0x53, 0xf1, 0xa1, 0x37, 0xe9, 0xe8, 0x2b, 0x67, 0xb8, 0xfd, 0xaf, 0x01, 0xbd, 0xa5, + 0x4a, 0x31, 0x73, 0x11, 0x89, 0x6a, 0xe1, 0x02, 0x80, 0xa0, 0x32, 0x44, 0x0c, 0x42, + 0x0a, 0x42, 0x1e, 0x94, 0x4d, 0x1e, 0x95, 0x2b, 0x70, 0xd5, 0x82, 0x6c, 0xd3, 0xb0, + 0x8b, 0x7d, 0xb9, 0x63, 0x0f, 0xe4, 0xfd, 0x5f, 0x22, 0x12, 0x5d, 0xe8, 0x40, 0xfc, + 0xc4, 0x0b, 0x98, 0x03, 0x8a, 0xf1, 0x1d, 0x55, 0xbe, 0x25, 0x43, 0x25, 0x97, 0xb4, + 0xb6, 0x5b, 0x9e, 0xc1, 0xc7, 0xa8, 0xbb, 0xfd, 0x05, 0x2c, 0xbf, 0x7e, 0x1c, 0x17, + 0x85, 0x31, 0x49, 0x34, 0xb2, 0x62, 0xd5, 0x85, 0x37, 0x54, 0xf1, 0xf1, 0x77, 0x71, + 0xcf, 0xb7, 0x50, 0x30, 0x72, 0x65, 0x57, 0x53, + ], + c_enc: [ + 0xe6, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, + 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, + 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, + 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0xac, 0xbe, 0x6e, 0x4d, + 0x87, 0xe9, 0x2a, 0xae, 0x2f, 0xe4, 0xe5, 0x8e, 0x78, 0x48, 0x69, 0xa9, 0x70, 0x68, + 0x4c, 0x9b, 0x87, 0xc9, 0xa1, 0xa0, 0xcc, 0x39, 0xb3, 0xbc, 0xce, 0xf4, 0x7c, 0xd7, + 0x6c, 0x23, 0x97, 0xb1, 0x43, 0x39, 0x5a, 0xd5, 0xbd, 0x5f, 0xe4, 0x22, 0x2c, 0x05, + 0xee, 0xb7, 0xc2, 0x0a, 0x5d, 0x0c, 0x35, 0xf0, 0x3a, 0xa2, 0xa6, 0xba, 0xfa, 0xdf, + 0x36, 0x3b, 0x1b, 0xa1, 0x5f, 0x8e, 0x75, 0x17, 0x79, 0x32, 0x03, 0xba, 0x09, 0x0e, + 0xda, 0x67, 0x1a, 0xcf, 0x48, 0xba, 0xaf, 0x8a, 0x6c, 0x1d, 0x55, 0xac, 0x76, 0x0b, + 0x10, 0xa0, 0x85, 0xb2, 0xe8, 0x33, 0xeb, 0x03, 0xb2, 0xbb, 0xd5, 0x21, 0x46, 0xd2, + 0x73, 0x19, 0xcc, 0x97, 0x13, 0x70, 0x14, 0xe7, 0x83, 0xac, 0xb6, 0x40, 0x27, 0xb6, + 0xea, 0x33, 0xa7, 0x1e, 0x54, 0xab, 0xb0, 0xe3, 0xf6, 0x05, 0x39, 0x10, 0xce, 0x33, + 0xa1, 0xc2, 0xde, 0x27, 0xd5, 0x80, 0x1a, 0x0d, 0xfc, 0x95, 0x28, 0xf8, 0x17, 0xb1, + 0x24, 0x88, 0x05, 0x62, 0xb7, 0x1f, 0xb9, 0x91, 0xd4, 0x1d, 0x2b, 0x4a, 0x20, 0x3b, + 0x3b, 0x20, 0x97, 0x55, 0xb6, 0x16, 0x8a, 0x99, 0x8c, 0xea, 0xb0, 0x2b, 0x21, 0x1e, + 0x49, 0xfe, 0x6a, 0xb1, 0x3a, 0x9a, 0x38, 0x83, 0xfe, 0xca, 0xfa, 0x87, 0x6d, 0xb2, + 0xbe, 0x99, 0x1a, 0x0a, 0xab, 0xb9, 0xf1, 0x50, 0xd5, 0xf1, 0xbf, 0xfc, 0x75, 0xbf, + 0x4d, 0xd0, 0xcf, 0x15, 0x09, 0xe5, 0x6b, 0x7e, 0xc8, 0x37, 0xdb, 0x74, 0xd1, 0xcb, + 0x2a, 0x10, 0x45, 0x1e, 0x1c, 0x04, 0xdd, 0xf9, 0x5b, 0x17, 0x20, 0x00, 0x94, 0x52, + 0xc5, 0x55, 0x86, 0x96, 0x35, 0x0e, 0xfd, 0xbf, 0x38, 0xc3, 0xde, 0x29, 0x98, 0x09, + 0x7c, 0xa7, 0xac, 0xd7, 0x09, 0x9a, 0x73, 0x94, 0x73, 0xc2, 0x07, 0x85, 0x89, 0xe7, + 0x18, 0xf9, 0x20, 0xad, 0xeb, 0xd6, 0xcb, 0x6e, 0xb1, 0x2e, 0x3f, 0xd2, 0x29, 0x47, + 0xa7, 0x6d, 0x19, 0x17, 0x45, 0xa6, 0xa9, 0x73, 0xc8, 0xb8, 0x4e, 0x9c, 0xd3, 0x30, + 0x7e, 0x47, 0x88, 0x81, 0xe9, 0x79, 0x8f, 0xd6, 0x66, 0x57, 0xec, 0xe5, 0xe0, 0x89, + 0xd6, 0x62, 0x71, 0x18, 0xc1, 0x1b, 0xa4, 0x01, 0xb0, 0x17, 0xdb, 0x2d, 0x6f, 0xf4, + 0x42, 0x10, 0xdb, 0x3e, 0x05, 0xaf, 0xe3, 0x10, 0x18, 0x79, 0xd9, 0x6f, 0x20, 0x2b, + 0x04, 0x93, 0x67, 0x2b, 0x55, 0x01, 0x3b, 0x26, 0x47, 0xad, 0x71, 0x7f, 0x8e, 0xf2, + 0x6f, 0x3d, 0x43, 0xb7, 0x75, 0x9e, 0xf5, 0xd6, 0x72, 0xcb, 0x14, 0x17, 0xf9, 0x78, + 0x81, 0xc3, 0x28, 0x80, 0x61, 0x2e, 0x6b, 0x00, 0xcc, 0x63, 0xfd, 0xa8, 0xd0, 0x29, + 0x88, 0xc4, 0x03, 0xee, 0x95, 0x6f, 0xfe, 0x72, 0xa2, 0xe1, 0xd1, 0x64, 0x29, 0x10, + 0xe3, 0xdf, 0x2c, 0xb8, 0xe0, 0xce, 0x90, 0x6f, 0x66, 0x2a, 0x96, 0x37, 0x5b, 0x78, + 0x64, 0xe1, 0x7f, 0x2a, 0x3d, 0x12, 0x19, 0x68, 0x47, 0x57, 0x03, 0x3c, 0xeb, 0x0c, + 0xb7, 0xea, 0x10, 0xd9, 0x90, 0x2d, 0x56, 0x55, 0x53, 0x15, 0xa8, 0x0f, 0x99, 0x7f, + 0xb7, 0xc3, 0xa6, 0xb7, 0x0e, 0x30, 0x7f, 0x33, 0x18, 0x44, 0x60, 0x1e, 0xf5, 0x70, + 0x13, 0xe3, 0xd3, 0x35, 0xfe, 0x48, 0x29, 0x81, 0xef, 0x72, 0x1f, 0xf0, 0xc3, 0x4f, + 0xb8, 0x8a, 0xcd, 0xae, 0x2f, 0xa0, 0xc1, 0x80, 0x1a, 0xd1, 0xe9, 0x67, 0x56, 0x25, + 0x66, 0xf7, 0xea, 0x6c, 0x65, 0x67, 0xfe, 0x06, 0x6d, 0x33, 0xd0, 0x84, 0x1b, 0x33, + 0xb5, 0x60, 0xe2, 0xf8, 0x43, 0x58, 0xd4, 0x1a, 0xfc, 0x3e, 0x43, 0x6d, 0x86, 0x8e, + 0x02, 0x1a, 0x1e, 0xde, 0xb3, 0x69, 0xa9, 0x84, 0x06, 0xa5, 0x76, 0xed, 0x48, 0x38, + 0xc7, 0x30, 0xad, 0xef, 0xd6, 0x94, 0x24, 0xc2, 0x35, 0xdb, 0x4f, 0xb1, 0xf6, 0xf6, + 0x2e, 0x9b, 0x51, 0x80, 0x5c, 0xdb, 0x43, 0xea, 0xf2, 0xa6, 0xb4, 0x5f, 0x81, 0x4d, + 0xaf, 0x53, 0x0a, 0xfb, 0xd0, 0xb3, 0x0b, 0xbb, 0xbb, 0xa9, 0x66, 0x05, 0x9a, 0x08, + 0xd3, 0x1d, 0x13, 0x7b, 0xbf, 0x5e, 0xc5, 0x80, 0x58, 0xd3, + ], + ock: [ + 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, + 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, + 0x3a, 0x5d, 0x91, 0xcb, + ], + op: [ + 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, + 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, + 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, + 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, + 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, + ], + c_out: [ + 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, + 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, + 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, + 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, + 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, + 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x0b, 0xb5, 0x6c, 0x49, 0xc0, 0x63, 0x2d, 0x4c, 0xc7, 0xe4, 0x85, 0x51, 0xdb, 0x46, + 0x42, 0x8f, 0x1b, 0x1a, 0x52, 0x66, 0x1e, 0x07, 0xe0, 0xc3, 0xbc, 0xc2, 0x31, 0x74, + 0xcc, 0xbb, 0xbd, 0xa1, 0xfa, 0x19, 0x24, 0xf4, 0x16, 0xcd, 0x48, 0x39, 0x0e, 0x2b, + 0x11, 0xc6, 0xe7, 0x82, 0x56, 0xd4, 0xc4, 0xc5, 0x64, 0x1a, 0xca, 0xd9, 0xa2, 0x0c, + 0x24, 0xfb, 0xe6, 0xcb, 0x4e, 0xe7, 0x81, 0x25, + ], + ovk: [ + 0x21, 0xe9, 0x1a, 0x3c, 0x4a, 0xa3, 0xf2, 0x7f, 0xa1, 0xb6, 0x33, 0x96, 0xe2, 0xb4, + 0x1d, 0xb9, 0x08, 0xfd, 0xab, 0x8b, 0x18, 0xcc, 0x73, 0x04, 0xe9, 0x4e, 0x97, 0x05, + 0x68, 0xf9, 0x42, 0x1c, + ], + default_d: [ + 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, + ], + default_pk_d: [ + 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, + 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, + 0x03, 0x8e, 0x3d, 0xb3, + ], + v: 12119135386131850622, + rseed: [ + 0xc3, 0x6d, 0xcf, 0xd3, 0x4a, 0x0c, 0xb6, 0x63, 0x78, 0x76, 0x10, 0x5e, 0x79, 0xbf, + 0x3b, 0xd5, 0x8e, 0xc1, 0x48, 0xcb, 0x64, 0x97, 0x0e, 0x32, 0x23, 0xa9, 0x1f, 0x71, + 0xdf, 0xcf, 0xd5, 0xa0, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x4b, 0x66, 0x7f, 0xba, 0xf3, 0xd4, 0xb3, 0xb9, 0x08, 0xb9, 0x82, 0x88, 0x20, + 0xdf, 0xec, 0xdd, 0x75, 0x37, 0x50, 0xb5, 0xf9, 0xd2, 0x21, 0x6e, 0x56, 0xc6, 0x15, + 0x27, 0x2f, 0x85, 0x44, 0x64, 0xc0, 0xca, 0x4b, 0x1e, 0x85, 0xae, 0xdd, 0x03, 0x82, + 0x92, 0xc4, 0xe1, 0xa5, 0x77, 0x44, 0xeb, 0xba, 0x01, 0x0b, 0x9e, 0xbf, 0xbb, 0x01, + 0x1b, 0xd6, 0xf0, 0xb7, 0x88, 0x05, 0x02, 0x5d, 0x27, 0xf3, 0xc1, 0x77, 0x46, 0xba, + 0xe1, 0x16, 0xc1, 0x5d, 0x9f, 0x47, 0x1f, 0x0f, 0x62, 0x88, 0xa1, 0x50, 0x64, 0x7b, + 0x2a, 0xfe, 0x9d, 0xf7, 0xcc, 0xcf, 0x01, 0xf5, 0xcd, 0xe5, 0xf0, 0x46, 0x80, 0xbb, + 0xfe, 0xd8, 0x7f, 0x6c, 0xf4, 0x29, 0xfb, 0x27, 0xad, 0x6b, 0xab, 0xe7, 0x91, 0x76, + 0x66, 0x11, 0xcf, 0x5b, 0xc2, 0x0e, 0x48, 0xbe, 0xf1, 0x19, 0x25, 0x9b, 0x9b, 0x8a, + 0x0e, 0x39, 0xc3, 0xdf, 0x28, 0xcb, 0x95, 0x82, 0xea, 0x33, 0x86, 0x01, 0xcd, 0xc4, + 0x81, 0xb3, 0x2f, 0xb8, 0x2a, 0xde, 0xeb, 0xb3, 0xda, 0xde, 0x25, 0xd1, 0xa3, 0xdf, + 0x20, 0xc3, 0x7e, 0x71, 0x25, 0x06, 0xb5, 0xd9, 0x96, 0xc4, 0x9a, 0x9f, 0x0f, 0x30, + 0xdd, 0xcb, 0x91, 0xfe, 0x90, 0x04, 0xe1, 0xe8, 0x32, 0x94, 0xa6, 0xc9, 0x20, 0x3d, + 0x94, 0xe8, 0xdc, 0x2c, 0xbb, 0x44, 0x9d, 0xe4, 0x15, 0x50, 0x32, 0x60, 0x4e, 0x47, + 0x99, 0x70, 0x16, 0xb3, 0x04, 0xfd, 0x43, 0x7d, 0x82, 0x35, 0x04, 0x5e, 0x25, 0x5a, + 0x19, 0xb7, 0x43, 0xa0, 0xa9, 0xf2, 0xe3, 0x36, 0xb4, 0x4c, 0xae, 0x30, 0x7b, 0xb3, + 0x98, 0x7b, 0xd3, 0xe4, 0xe7, 0x77, 0xfb, 0xb3, 0x4c, 0x0a, 0xb8, 0xcc, 0x3d, 0x67, + 0x46, 0x6c, 0x0a, 0x88, 0xdd, 0x4c, 0xca, 0xd1, 0x8a, 0x07, 0xa8, 0xd1, 0x06, 0x8d, + 0xf5, 0xb6, 0x29, 0xe5, 0x71, 0x8d, 0x0f, 0x6d, 0xf5, 0xc9, 0x57, 0xcf, 0x71, 0xbb, + 0x00, 0xa5, 0x17, 0x8f, 0x17, 0x5c, 0xac, 0xa9, 0x44, 0xe6, 0x35, 0xc5, 0x15, 0x9f, + 0x73, 0x8e, 0x24, 0x02, 0xa2, 0xd2, 0x1a, 0xa0, 0x81, 0xe1, 0x0e, 0x45, 0x6a, 0xfb, + 0x00, 0xb9, 0xf6, 0x24, 0x16, 0xc8, 0xb9, 0xc0, 0xf7, 0x22, 0x8f, 0x51, 0x07, 0x29, + 0xe0, 0xbe, 0x3f, 0x30, 0x53, 0x13, 0xd7, 0x7f, 0x73, 0x79, 0xdc, 0x2a, 0xf2, 0x48, + 0x69, 0xc6, 0xc7, 0x4e, 0xe4, 0x47, 0x14, 0x98, 0x86, 0x1d, 0x19, 0x2f, 0x0f, 0xf0, + 0xf5, 0x08, 0x28, 0x5d, 0xab, 0x6b, 0x6a, 0x36, 0xcc, 0xf7, 0xd1, 0x22, 0x56, 0xcc, + 0x76, 0xb9, 0x55, 0x03, 0x72, 0x0a, 0xc6, 0x72, 0xd0, 0x82, 0x68, 0xd2, 0xcf, 0x77, + 0x73, 0xb6, 0xba, 0x2a, 0x5f, 0x66, 0x48, 0x47, 0xbf, 0x70, 0x7f, 0x2f, 0xc1, 0x0c, + 0x98, 0xf2, 0xf0, 0x06, 0xec, 0x22, 0xcc, 0xb5, 0xa8, 0xc8, 0xb7, 0xc4, 0x0c, 0x7c, + 0x2d, 0x49, 0xa6, 0x63, 0x9b, 0x9f, 0x2c, 0xe3, 0x3c, 0x25, 0xc0, 0x4b, 0xc4, 0x61, + 0xe7, 0x44, 0xdf, 0xa5, 0x36, 0xb0, 0x0d, 0x94, 0xba, 0xdd, 0xf4, 0xf4, 0xd1, 0x40, + 0x44, 0xc6, 0x95, 0xa3, 0x38, 0x81, 0x47, 0x7d, 0xf1, 0x24, 0xf0, 0xfc, 0xf2, 0x06, + 0xa9, 0xfb, 0x2e, 0x65, 0xe3, 0x04, 0xcd, 0xbf, 0x0c, 0x4d, 0x23, 0x90, 0x17, 0x0c, + 0x13, 0x0a, 0xb8, 0x49, 0xc2, 0xf2, 0x2b, 0x5c, 0xdd, 0x39, 0x21, 0x64, 0x0c, 0x8c, + 0xf1, 0x97, 0x6a, 0xe1, 0x01, 0x0b, 0x0d, 0xfd, 0x9c, 0xb2, 0x54, 0x3e, 0x45, 0xf9, + 0x97, 0x49, 0xcc, 0x4d, 0x61, 0xf2, 0xe8, 0xaa, 0xbf, 0xe9, 0x8b, 0xd9, 0x05, 0xfa, + 0x39, 0x95, 0x1b, 0x33, 0xea, 0x76, 0x9c, 0x45, 0xab, 0x95, 0x31, 0xc5, 0x72, 0x09, + 0x86, 0x2a, 0xd1, 0x2f, 0xd7, 0x6b, 0xa4, 0x80, + ], + cv_net: [ + 0xca, 0xf6, 0x40, 0x8d, 0xef, 0x1f, 0x0f, 0x2b, 0xaa, 0x17, 0xb1, 0x30, 0xc3, 0xae, + 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, + 0xd2, 0x50, 0x21, 0x17, + ], + nf_old: [ + 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, + 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, + 0x3c, 0xfb, 0xf1, 0x31, + ], + cmx: [ + 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, + 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, + 0xc9, 0x65, 0x79, 0x10, + ], + esk: [ + 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, + 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, + 0x06, 0x15, 0xb2, 0x0d, + ], + ephemeral_key: [ + 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, + 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, + 0x1b, 0xb1, 0x69, 0x26, + ], + shared_secret: [ + 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, + 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, + 0x3a, 0x30, 0x1e, 0x23, + ], + k_enc: [ + 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, + 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, + 0xf3, 0x81, 0x58, 0xc4, + ], + p_enc: [ + 0x03, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, + 0x41, 0x7b, 0x6c, 0xd1, 0x2f, 0xa8, 0xc3, 0x6d, 0xcf, 0xd3, 0x4a, 0x0c, 0xb6, 0x63, + 0x78, 0x76, 0x10, 0x5e, 0x79, 0xbf, 0x3b, 0xd5, 0x8e, 0xc1, 0x48, 0xcb, 0x64, 0x97, + 0x0e, 0x32, 0x23, 0xa9, 0x1f, 0x71, 0xdf, 0xcf, 0xd5, 0xa0, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x4b, 0x66, 0x7f, 0xba, 0xf3, 0xd4, 0xb3, 0xb9, 0x08, 0xb9, 0x82, 0x88, 0x20, + 0xdf, 0xec, 0xdd, 0x75, 0x37, 0x50, 0xb5, 0xf9, 0xd2, 0x21, 0x6e, 0x56, 0xc6, 0x15, + 0x27, 0x2f, 0x85, 0x44, 0x64, 0xc0, 0xca, 0x4b, 0x1e, 0x85, 0xae, 0xdd, 0x03, 0x82, + 0x92, 0xc4, 0xe1, 0xa5, 0x77, 0x44, 0xeb, 0xba, 0x01, 0x0b, 0x9e, 0xbf, 0xbb, 0x01, + 0x1b, 0xd6, 0xf0, 0xb7, 0x88, 0x05, 0x02, 0x5d, 0x27, 0xf3, 0xc1, 0x77, 0x46, 0xba, + 0xe1, 0x16, 0xc1, 0x5d, 0x9f, 0x47, 0x1f, 0x0f, 0x62, 0x88, 0xa1, 0x50, 0x64, 0x7b, + 0x2a, 0xfe, 0x9d, 0xf7, 0xcc, 0xcf, 0x01, 0xf5, 0xcd, 0xe5, 0xf0, 0x46, 0x80, 0xbb, + 0xfe, 0xd8, 0x7f, 0x6c, 0xf4, 0x29, 0xfb, 0x27, 0xad, 0x6b, 0xab, 0xe7, 0x91, 0x76, + 0x66, 0x11, 0xcf, 0x5b, 0xc2, 0x0e, 0x48, 0xbe, 0xf1, 0x19, 0x25, 0x9b, 0x9b, 0x8a, + 0x0e, 0x39, 0xc3, 0xdf, 0x28, 0xcb, 0x95, 0x82, 0xea, 0x33, 0x86, 0x01, 0xcd, 0xc4, + 0x81, 0xb3, 0x2f, 0xb8, 0x2a, 0xde, 0xeb, 0xb3, 0xda, 0xde, 0x25, 0xd1, 0xa3, 0xdf, + 0x20, 0xc3, 0x7e, 0x71, 0x25, 0x06, 0xb5, 0xd9, 0x96, 0xc4, 0x9a, 0x9f, 0x0f, 0x30, + 0xdd, 0xcb, 0x91, 0xfe, 0x90, 0x04, 0xe1, 0xe8, 0x32, 0x94, 0xa6, 0xc9, 0x20, 0x3d, + 0x94, 0xe8, 0xdc, 0x2c, 0xbb, 0x44, 0x9d, 0xe4, 0x15, 0x50, 0x32, 0x60, 0x4e, 0x47, + 0x99, 0x70, 0x16, 0xb3, 0x04, 0xfd, 0x43, 0x7d, 0x82, 0x35, 0x04, 0x5e, 0x25, 0x5a, + 0x19, 0xb7, 0x43, 0xa0, 0xa9, 0xf2, 0xe3, 0x36, 0xb4, 0x4c, 0xae, 0x30, 0x7b, 0xb3, + 0x98, 0x7b, 0xd3, 0xe4, 0xe7, 0x77, 0xfb, 0xb3, 0x4c, 0x0a, 0xb8, 0xcc, 0x3d, 0x67, + 0x46, 0x6c, 0x0a, 0x88, 0xdd, 0x4c, 0xca, 0xd1, 0x8a, 0x07, 0xa8, 0xd1, 0x06, 0x8d, + 0xf5, 0xb6, 0x29, 0xe5, 0x71, 0x8d, 0x0f, 0x6d, 0xf5, 0xc9, 0x57, 0xcf, 0x71, 0xbb, + 0x00, 0xa5, 0x17, 0x8f, 0x17, 0x5c, 0xac, 0xa9, 0x44, 0xe6, 0x35, 0xc5, 0x15, 0x9f, + 0x73, 0x8e, 0x24, 0x02, 0xa2, 0xd2, 0x1a, 0xa0, 0x81, 0xe1, 0x0e, 0x45, 0x6a, 0xfb, + 0x00, 0xb9, 0xf6, 0x24, 0x16, 0xc8, 0xb9, 0xc0, 0xf7, 0x22, 0x8f, 0x51, 0x07, 0x29, + 0xe0, 0xbe, 0x3f, 0x30, 0x53, 0x13, 0xd7, 0x7f, 0x73, 0x79, 0xdc, 0x2a, 0xf2, 0x48, + 0x69, 0xc6, 0xc7, 0x4e, 0xe4, 0x47, 0x14, 0x98, 0x86, 0x1d, 0x19, 0x2f, 0x0f, 0xf0, + 0xf5, 0x08, 0x28, 0x5d, 0xab, 0x6b, 0x6a, 0x36, 0xcc, 0xf7, 0xd1, 0x22, 0x56, 0xcc, + 0x76, 0xb9, 0x55, 0x03, 0x72, 0x0a, 0xc6, 0x72, 0xd0, 0x82, 0x68, 0xd2, 0xcf, 0x77, + 0x73, 0xb6, 0xba, 0x2a, 0x5f, 0x66, 0x48, 0x47, 0xbf, 0x70, 0x7f, 0x2f, 0xc1, 0x0c, + 0x98, 0xf2, 0xf0, 0x06, 0xec, 0x22, 0xcc, 0xb5, 0xa8, 0xc8, 0xb7, 0xc4, 0x0c, 0x7c, + 0x2d, 0x49, 0xa6, 0x63, 0x9b, 0x9f, 0x2c, 0xe3, 0x3c, 0x25, 0xc0, 0x4b, 0xc4, 0x61, + 0xe7, 0x44, 0xdf, 0xa5, 0x36, 0xb0, 0x0d, 0x94, 0xba, 0xdd, 0xf4, 0xf4, 0xd1, 0x40, + 0x44, 0xc6, 0x95, 0xa3, 0x38, 0x81, 0x47, 0x7d, 0xf1, 0x24, 0xf0, 0xfc, 0xf2, 0x06, + 0xa9, 0xfb, 0x2e, 0x65, 0xe3, 0x04, 0xcd, 0xbf, 0x0c, 0x4d, 0x23, 0x90, 0x17, 0x0c, + 0x13, 0x0a, 0xb8, 0x49, 0xc2, 0xf2, 0x2b, 0x5c, 0xdd, 0x39, 0x21, 0x64, 0x0c, 0x8c, + 0xf1, 0x97, 0x6a, 0xe1, 0x01, 0x0b, 0x0d, 0xfd, 0x9c, 0xb2, 0x54, 0x3e, 0x45, 0xf9, + 0x97, 0x49, 0xcc, 0x4d, 0x61, 0xf2, 0xe8, 0xaa, 0xbf, 0xe9, 0x8b, 0xd9, 0x05, 0xfa, + 0x39, 0x95, 0x1b, 0x33, 0xea, 0x76, 0x9c, 0x45, 0xab, 0x95, 0x31, 0xc5, 0x72, 0x09, + 0x86, 0x2a, 0xd1, 0x2f, 0xd7, 0x6b, 0xa4, 0x80, + ], + c_enc: [ + 0x3e, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, + 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, + 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, + 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0xa4, 0x13, 0xfa, 0x5f, + 0x49, 0xaf, 0xc6, 0x58, 0x93, 0x94, 0xab, 0x86, 0x59, 0x0c, 0x43, 0x78, 0x5a, 0x58, + 0x0b, 0xd2, 0x86, 0x0b, 0xe3, 0xb8, 0x07, 0x99, 0xc1, 0x47, 0xf4, 0xe6, 0xc7, 0x50, + 0x31, 0x36, 0x76, 0x9a, 0xe4, 0xc6, 0x2c, 0xd9, 0x16, 0x9d, 0xd3, 0x66, 0xb8, 0x99, + 0xa5, 0x44, 0x8c, 0xdb, 0xc4, 0x0c, 0x8d, 0x89, 0x60, 0x38, 0x6c, 0x0f, 0x0e, 0x3e, + 0x74, 0x03, 0xd2, 0x6e, 0x66, 0xa5, 0x99, 0x40, 0xe7, 0x6a, 0xc7, 0x9d, 0xd1, 0xea, + 0xea, 0x55, 0xd0, 0xc0, 0x9f, 0x3b, 0xf6, 0xd9, 0xdc, 0xea, 0xe1, 0xee, 0x87, 0x41, + 0x38, 0x39, 0x1a, 0x0c, 0x93, 0x3e, 0x7b, 0x72, 0x75, 0xd7, 0x3b, 0x8e, 0xf4, 0x9b, + 0x8c, 0x39, 0x5c, 0x87, 0xfd, 0x32, 0x09, 0xe1, 0xf5, 0xa9, 0xc5, 0x52, 0xe6, 0x11, + 0x2b, 0xd9, 0xf3, 0xea, 0xb6, 0xbd, 0x4f, 0x26, 0xab, 0xa6, 0x4d, 0xb8, 0x27, 0xa7, + 0x1b, 0x86, 0x53, 0x9c, 0xf9, 0x72, 0x96, 0xfe, 0xca, 0x46, 0x27, 0x3e, 0xf4, 0x56, + 0xfe, 0x16, 0x0b, 0x31, 0xc7, 0x72, 0xcf, 0xf6, 0x82, 0xa6, 0xed, 0x06, 0x10, 0x93, + 0x14, 0x6e, 0xa6, 0x57, 0xf4, 0x61, 0xb5, 0x6f, 0xb2, 0x3c, 0x20, 0x64, 0xd8, 0x98, + 0xec, 0x25, 0x70, 0x34, 0x3c, 0x56, 0x6a, 0xdc, 0x1f, 0x2d, 0x1d, 0x86, 0x48, 0x41, + 0x42, 0x2e, 0x96, 0x4a, 0x4a, 0xb8, 0x3c, 0x18, 0x95, 0x0f, 0x82, 0xfa, 0x97, 0x4c, + 0x83, 0x3c, 0xf7, 0x62, 0x3d, 0xa9, 0xb8, 0xbe, 0xec, 0x7a, 0x1e, 0xbf, 0x5c, 0xeb, + 0x22, 0x25, 0xc1, 0xf2, 0xda, 0x30, 0xd0, 0x47, 0x9d, 0xbb, 0xa1, 0x68, 0x1f, 0x6e, + 0x75, 0xf2, 0xfa, 0xce, 0x30, 0x70, 0xe7, 0xa8, 0x13, 0xaa, 0x88, 0x34, 0x72, 0xae, + 0x47, 0x7c, 0x47, 0xbc, 0x2e, 0xc2, 0xe5, 0xc6, 0xcd, 0x85, 0x5d, 0x12, 0x25, 0x7c, + 0x54, 0xbd, 0xea, 0xdc, 0x44, 0x3b, 0xe7, 0xd6, 0xb6, 0x7d, 0x11, 0xad, 0xd4, 0x1f, + 0x49, 0xa9, 0xb4, 0xd8, 0x13, 0x8f, 0xd8, 0x7c, 0x0d, 0xee, 0x7f, 0x5f, 0xae, 0x0c, + 0xd8, 0x83, 0x7c, 0x39, 0xdb, 0x19, 0x9e, 0xea, 0x34, 0x48, 0xa9, 0x41, 0x05, 0x1f, + 0x78, 0x5c, 0x1f, 0x8a, 0xd0, 0xb2, 0x65, 0xd8, 0x78, 0x7c, 0x70, 0x1d, 0xe0, 0x5b, + 0xf1, 0xc6, 0x6a, 0x3d, 0x65, 0x94, 0xf5, 0x22, 0x19, 0xcc, 0xb3, 0x1e, 0x05, 0x03, + 0x9c, 0x83, 0x02, 0x2a, 0xa8, 0x61, 0x21, 0x1c, 0x50, 0xc2, 0xf0, 0xcf, 0xb1, 0xbe, + 0x94, 0x45, 0xcd, 0xb9, 0x6d, 0xf0, 0x0a, 0x16, 0x67, 0x57, 0x1a, 0x68, 0xb7, 0xf2, + 0x19, 0x45, 0xb1, 0xfa, 0xef, 0x4e, 0xbc, 0xcf, 0xa1, 0xc5, 0x83, 0xc4, 0x66, 0xb0, + 0xef, 0x58, 0x8a, 0xcd, 0xfd, 0x47, 0x8c, 0x7f, 0x21, 0x22, 0x61, 0x12, 0x8a, 0xf4, + 0x25, 0xa2, 0xe0, 0xa3, 0xa2, 0x7e, 0x17, 0x48, 0x7f, 0xff, 0x08, 0xb9, 0xfb, 0x80, + 0xd8, 0xaa, 0x71, 0x8f, 0xe2, 0x67, 0xda, 0xbc, 0x70, 0xd3, 0x6b, 0x8f, 0x62, 0xe0, + 0xe9, 0x04, 0x33, 0x47, 0x01, 0x4e, 0x02, 0xa2, 0x7a, 0x85, 0x79, 0x97, 0xe1, 0xcf, + 0x3e, 0x72, 0x33, 0xe2, 0x51, 0x3f, 0x83, 0x2e, 0x60, 0x35, 0x91, 0x68, 0xe1, 0x73, + 0xfc, 0x03, 0x07, 0x9e, 0x99, 0x83, 0xa1, 0x34, 0x1d, 0x68, 0xbb, 0x3a, 0x3c, 0x53, + 0x3a, 0x31, 0x84, 0xf4, 0xaa, 0x41, 0x75, 0xa9, 0xfe, 0xc1, 0xf0, 0x1f, 0xe3, 0xf8, + 0xb4, 0xfa, 0xeb, 0xed, 0x30, 0xb7, 0xe7, 0x18, 0x0e, 0x7e, 0xd7, 0xfc, 0x80, 0x7d, + 0x51, 0x0c, 0x06, 0x01, 0x42, 0x8d, 0xd6, 0x96, 0x41, 0xa3, 0x07, 0x29, 0xcd, 0x64, + 0x45, 0xde, 0x66, 0x0f, 0xb1, 0xbe, 0x2f, 0xb9, 0x6e, 0x56, 0xbb, 0x67, 0xb6, 0xef, + 0x88, 0xe0, 0x7d, 0x14, 0xae, 0xda, 0xa0, 0xbd, 0x23, 0x27, 0xe9, 0xd5, 0x27, 0xb7, + 0xe3, 0x30, 0x07, 0xf8, 0xca, 0xb5, 0x10, 0xad, 0xc2, 0x53, 0xca, 0xe6, 0x68, 0x7f, + 0xfd, 0xc9, 0x60, 0x40, 0x30, 0x40, 0x15, 0x9a, 0x7e, 0x98, 0xda, 0xa8, 0xa7, 0x7b, + 0x2a, 0x3f, 0xdf, 0x4f, 0x79, 0xd5, 0xbd, 0xbe, 0x9e, 0x2b, + ], + ock: [ + 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, + 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, + 0x50, 0xc5, 0xcf, 0x2d, + ], + op: [ + 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, + 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, + 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, + 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, + 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, + ], + c_out: [ + 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, + 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, + 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, + 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, + 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, + 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xeb, 0xd4, 0x80, 0x6d, 0x81, 0x25, 0x49, 0x89, 0xfa, 0xdb, 0xa8, 0xcd, 0x58, 0x96, + 0x7d, 0x6f, 0xd8, 0x73, 0x83, 0xbc, 0x09, 0x38, 0x63, 0xd5, 0xab, 0xfc, 0xdd, 0xd3, + 0x8f, 0x15, 0x39, 0xfa, 0xb7, 0xe5, 0xd4, 0xf0, 0x61, 0x91, 0x67, 0xb8, 0xd4, 0x82, + 0xcb, 0x54, 0x8c, 0xb5, 0x59, 0x83, 0x49, 0x6f, 0x77, 0xd3, 0xdc, 0xaf, 0xf5, 0x6e, + 0x32, 0x41, 0x0b, 0xfe, 0xc1, 0xf2, 0x68, 0x11, + ], + ovk: [ + 0xb2, 0x5f, 0x30, 0x3f, 0x58, 0x15, 0xc4, 0x53, 0x31, 0x24, 0xac, 0xf9, 0xd1, 0x89, + 0x40, 0xe7, 0x75, 0x22, 0xac, 0x5d, 0xc4, 0xb9, 0x57, 0x0a, 0xae, 0x8f, 0x47, 0xb7, + 0xf5, 0x7f, 0xd8, 0x76, + ], + default_d: [ + 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, + ], + default_pk_d: [ + 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, + 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, + 0x67, 0xa8, 0x60, 0x9e, + ], + v: 9624581763228770449, + rseed: [ + 0x4a, 0x95, 0xb2, 0x05, 0x52, 0x6c, 0xfc, 0xb4, 0xc4, 0xe1, 0xcc, 0x95, 0x51, 0x75, + 0xb3, 0xe8, 0xde, 0x1f, 0x5d, 0x81, 0xb1, 0x86, 0x69, 0x69, 0x23, 0x50, 0xaa, 0xa1, + 0xa1, 0xd7, 0x97, 0x61, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x75, 0x82, 0xe5, 0x4d, 0x7a, 0x5b, 0x57, 0xa6, 0x83, 0xb3, 0x2f, 0xb1, 0x09, + 0x80, 0x62, 0xda, 0xd7, 0xb0, 0xc2, 0xeb, 0x51, 0x8f, 0x68, 0x62, 0xe8, 0x3d, 0xb2, + 0x5e, 0x3d, 0xba, 0xf7, 0xae, 0xd5, 0x04, 0xde, 0x93, 0x2a, 0xcb, 0x99, 0xd7, 0x35, + 0x99, 0x2c, 0xe6, 0x2b, 0xae, 0x9e, 0xf8, 0x93, 0xff, 0x6a, 0xcc, 0x0f, 0xfc, 0xf8, + 0xe3, 0x48, 0x3e, 0x14, 0x6b, 0x9d, 0x49, 0xdd, 0x8c, 0x78, 0x35, 0xf4, 0x3a, 0x37, + 0xdc, 0xa0, 0x78, 0x7e, 0x3e, 0xc9, 0xf6, 0x60, 0x52, 0x23, 0xd5, 0xba, 0x7a, 0xe0, + 0xab, 0x90, 0x25, 0xb7, 0x3b, 0xc0, 0x3f, 0x7f, 0xac, 0x36, 0xc0, 0x09, 0xa5, 0x6d, + 0x4d, 0x95, 0xd1, 0xe8, 0x1d, 0x3b, 0x3e, 0xbc, 0xa7, 0xe5, 0x4c, 0xc1, 0xa1, 0x2d, + 0x12, 0x7b, 0x57, 0xc8, 0x13, 0x89, 0x76, 0xe7, 0x91, 0x01, 0x3b, 0x01, 0x5f, 0x06, + 0xa6, 0x24, 0xf5, 0x21, 0xb6, 0xee, 0x04, 0xec, 0x98, 0x08, 0x93, 0xc7, 0xe5, 0xe0, + 0x1a, 0x33, 0x62, 0x03, 0x59, 0x40, 0x94, 0xf8, 0x28, 0x33, 0xd7, 0x44, 0x5f, 0xe2, + 0xd0, 0x91, 0x30, 0xf6, 0x35, 0x11, 0xda, 0x54, 0x83, 0x2d, 0xe9, 0x13, 0x6b, 0x39, + 0xf4, 0x59, 0x9f, 0x5a, 0xa5, 0xdf, 0xbb, 0x45, 0xda, 0x60, 0xcd, 0xce, 0xab, 0x7e, + 0xef, 0xde, 0x89, 0xbe, 0x63, 0xf3, 0xf7, 0xc0, 0xd2, 0x32, 0x48, 0x47, 0xcc, 0xe1, + 0x40, 0x5d, 0xef, 0x7c, 0x46, 0x9b, 0x0e, 0x27, 0x24, 0x94, 0xe5, 0xdf, 0x54, 0xf5, + 0x68, 0x65, 0x6c, 0xb9, 0xc8, 0x81, 0x8d, 0x92, 0xb7, 0x2b, 0x8b, 0xc3, 0x4d, 0xb7, + 0xbb, 0x31, 0x12, 0x48, 0x7e, 0x74, 0x6e, 0xef, 0xe4, 0xe8, 0x08, 0xbb, 0xb2, 0x87, + 0xd9, 0x9b, 0xf0, 0x7d, 0x00, 0xda, 0xbe, 0xde, 0xdc, 0x5e, 0x5f, 0x07, 0x4f, 0xfe, + 0xae, 0x0c, 0xba, 0x7d, 0xa3, 0xa5, 0x16, 0xc1, 0x73, 0xbe, 0x1c, 0x51, 0x33, 0x23, + 0xe1, 0x19, 0xf6, 0x35, 0xe8, 0x20, 0x9a, 0x07, 0x4b, 0x21, 0x6b, 0x70, 0x23, 0xfa, + 0xdc, 0x2d, 0x25, 0x94, 0x9c, 0x90, 0x03, 0x7e, 0x71, 0xe3, 0xe5, 0x50, 0x72, 0x6d, + 0x21, 0x0a, 0x2c, 0x68, 0x83, 0x42, 0xe5, 0x24, 0x40, 0x63, 0x5e, 0x9c, 0xc1, 0x4a, + 0xfe, 0x10, 0x10, 0x26, 0x21, 0xa9, 0xc9, 0xac, 0xcb, 0x78, 0x2e, 0x9e, 0x4a, 0x5f, + 0xa8, 0x7f, 0x0a, 0x95, 0x6f, 0x5b, 0x85, 0x50, 0x99, 0x60, 0x28, 0x5c, 0x22, 0x62, + 0x7c, 0x59, 0x48, 0x3a, 0x5a, 0x4c, 0x28, 0xcc, 0xe4, 0xb1, 0x56, 0xe5, 0x51, 0x40, + 0x6a, 0x7e, 0xe8, 0x35, 0x56, 0x56, 0xa2, 0x1e, 0x43, 0xe3, 0x8c, 0xe1, 0x29, 0xfd, + 0xad, 0xb7, 0x59, 0xed, 0xdf, 0xa0, 0x8f, 0x00, 0xfc, 0x8e, 0x56, 0x7c, 0xef, 0x93, + 0xc6, 0x79, 0x2d, 0x01, 0xdf, 0x05, 0xe6, 0xd5, 0x80, 0xf4, 0xd5, 0xd4, 0x8d, 0xf0, + 0x42, 0x45, 0x1a, 0x33, 0x59, 0x0d, 0x3e, 0x8c, 0xf4, 0x9b, 0x26, 0x27, 0x21, 0x8f, + 0x0c, 0x29, 0x2f, 0xa6, 0x6a, 0xda, 0x94, 0x5f, 0xa5, 0x5b, 0xb2, 0x35, 0x48, 0xe3, + 0x3a, 0x83, 0xa5, 0x62, 0x95, 0x7a, 0x31, 0x49, 0xa9, 0x93, 0xcc, 0x47, 0x23, 0x62, + 0x29, 0x87, 0x36, 0xa8, 0xb7, 0x78, 0xd9, 0x7c, 0xe4, 0x23, 0x01, 0x3d, 0x64, 0xb3, + 0x2c, 0xd1, 0x72, 0xef, 0xa5, 0x51, 0xbf, 0x7f, 0x36, 0x8f, 0x04, 0xbd, 0xae, 0xc6, + 0x09, 0x1a, 0x30, 0x04, 0xa7, 0x57, 0x59, 0x8b, 0x80, 0x1d, 0xcf, 0x67, 0x5c, 0xb8, + 0x3e, 0x43, 0xa5, 0x3a, 0xe8, 0xb2, 0x54, 0xd3, 0x33, 0xbc, 0xda, 0x20, 0xd4, 0x81, + 0x7d, 0x34, 0x77, 0xab, 0xfb, 0xa2, 0x5b, 0xb8, 0x3d, 0xf5, 0x94, 0x9c, 0x12, 0x6f, + 0x14, 0x9b, 0x1d, 0x99, 0x34, 0x1e, 0x4e, 0x6f, + ], + cv_net: [ + 0xd2, 0xf9, 0xad, 0xff, 0x53, 0x1b, 0x65, 0x43, 0x2b, 0xa2, 0xd7, 0xda, 0xa6, 0xd8, + 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, + 0xda, 0x6b, 0x15, 0x14, + ], + nf_old: [ + 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, + 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, + 0x21, 0x38, 0xab, 0x29, + ], + cmx: [ + 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, + 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, + 0x97, 0xf8, 0x9c, 0x20, + ], + esk: [ + 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, + 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, + 0xcc, 0xd5, 0x4e, 0x3a, + ], + ephemeral_key: [ + 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, + 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, + 0xd3, 0xbf, 0x0e, 0x8f, + ], + shared_secret: [ + 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, + 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, + 0x61, 0xfd, 0xaf, 0xb5, + ], + k_enc: [ + 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, + 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, + 0x18, 0x06, 0x9e, 0x99, + ], + p_enc: [ + 0x03, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, + 0xf4, 0xd4, 0x1e, 0x62, 0x91, 0x85, 0x4a, 0x95, 0xb2, 0x05, 0x52, 0x6c, 0xfc, 0xb4, + 0xc4, 0xe1, 0xcc, 0x95, 0x51, 0x75, 0xb3, 0xe8, 0xde, 0x1f, 0x5d, 0x81, 0xb1, 0x86, + 0x69, 0x69, 0x23, 0x50, 0xaa, 0xa1, 0xa1, 0xd7, 0x97, 0x61, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x75, 0x82, 0xe5, 0x4d, 0x7a, 0x5b, 0x57, 0xa6, 0x83, 0xb3, 0x2f, 0xb1, 0x09, + 0x80, 0x62, 0xda, 0xd7, 0xb0, 0xc2, 0xeb, 0x51, 0x8f, 0x68, 0x62, 0xe8, 0x3d, 0xb2, + 0x5e, 0x3d, 0xba, 0xf7, 0xae, 0xd5, 0x04, 0xde, 0x93, 0x2a, 0xcb, 0x99, 0xd7, 0x35, + 0x99, 0x2c, 0xe6, 0x2b, 0xae, 0x9e, 0xf8, 0x93, 0xff, 0x6a, 0xcc, 0x0f, 0xfc, 0xf8, + 0xe3, 0x48, 0x3e, 0x14, 0x6b, 0x9d, 0x49, 0xdd, 0x8c, 0x78, 0x35, 0xf4, 0x3a, 0x37, + 0xdc, 0xa0, 0x78, 0x7e, 0x3e, 0xc9, 0xf6, 0x60, 0x52, 0x23, 0xd5, 0xba, 0x7a, 0xe0, + 0xab, 0x90, 0x25, 0xb7, 0x3b, 0xc0, 0x3f, 0x7f, 0xac, 0x36, 0xc0, 0x09, 0xa5, 0x6d, + 0x4d, 0x95, 0xd1, 0xe8, 0x1d, 0x3b, 0x3e, 0xbc, 0xa7, 0xe5, 0x4c, 0xc1, 0xa1, 0x2d, + 0x12, 0x7b, 0x57, 0xc8, 0x13, 0x89, 0x76, 0xe7, 0x91, 0x01, 0x3b, 0x01, 0x5f, 0x06, + 0xa6, 0x24, 0xf5, 0x21, 0xb6, 0xee, 0x04, 0xec, 0x98, 0x08, 0x93, 0xc7, 0xe5, 0xe0, + 0x1a, 0x33, 0x62, 0x03, 0x59, 0x40, 0x94, 0xf8, 0x28, 0x33, 0xd7, 0x44, 0x5f, 0xe2, + 0xd0, 0x91, 0x30, 0xf6, 0x35, 0x11, 0xda, 0x54, 0x83, 0x2d, 0xe9, 0x13, 0x6b, 0x39, + 0xf4, 0x59, 0x9f, 0x5a, 0xa5, 0xdf, 0xbb, 0x45, 0xda, 0x60, 0xcd, 0xce, 0xab, 0x7e, + 0xef, 0xde, 0x89, 0xbe, 0x63, 0xf3, 0xf7, 0xc0, 0xd2, 0x32, 0x48, 0x47, 0xcc, 0xe1, + 0x40, 0x5d, 0xef, 0x7c, 0x46, 0x9b, 0x0e, 0x27, 0x24, 0x94, 0xe5, 0xdf, 0x54, 0xf5, + 0x68, 0x65, 0x6c, 0xb9, 0xc8, 0x81, 0x8d, 0x92, 0xb7, 0x2b, 0x8b, 0xc3, 0x4d, 0xb7, + 0xbb, 0x31, 0x12, 0x48, 0x7e, 0x74, 0x6e, 0xef, 0xe4, 0xe8, 0x08, 0xbb, 0xb2, 0x87, + 0xd9, 0x9b, 0xf0, 0x7d, 0x00, 0xda, 0xbe, 0xde, 0xdc, 0x5e, 0x5f, 0x07, 0x4f, 0xfe, + 0xae, 0x0c, 0xba, 0x7d, 0xa3, 0xa5, 0x16, 0xc1, 0x73, 0xbe, 0x1c, 0x51, 0x33, 0x23, + 0xe1, 0x19, 0xf6, 0x35, 0xe8, 0x20, 0x9a, 0x07, 0x4b, 0x21, 0x6b, 0x70, 0x23, 0xfa, + 0xdc, 0x2d, 0x25, 0x94, 0x9c, 0x90, 0x03, 0x7e, 0x71, 0xe3, 0xe5, 0x50, 0x72, 0x6d, + 0x21, 0x0a, 0x2c, 0x68, 0x83, 0x42, 0xe5, 0x24, 0x40, 0x63, 0x5e, 0x9c, 0xc1, 0x4a, + 0xfe, 0x10, 0x10, 0x26, 0x21, 0xa9, 0xc9, 0xac, 0xcb, 0x78, 0x2e, 0x9e, 0x4a, 0x5f, + 0xa8, 0x7f, 0x0a, 0x95, 0x6f, 0x5b, 0x85, 0x50, 0x99, 0x60, 0x28, 0x5c, 0x22, 0x62, + 0x7c, 0x59, 0x48, 0x3a, 0x5a, 0x4c, 0x28, 0xcc, 0xe4, 0xb1, 0x56, 0xe5, 0x51, 0x40, + 0x6a, 0x7e, 0xe8, 0x35, 0x56, 0x56, 0xa2, 0x1e, 0x43, 0xe3, 0x8c, 0xe1, 0x29, 0xfd, + 0xad, 0xb7, 0x59, 0xed, 0xdf, 0xa0, 0x8f, 0x00, 0xfc, 0x8e, 0x56, 0x7c, 0xef, 0x93, + 0xc6, 0x79, 0x2d, 0x01, 0xdf, 0x05, 0xe6, 0xd5, 0x80, 0xf4, 0xd5, 0xd4, 0x8d, 0xf0, + 0x42, 0x45, 0x1a, 0x33, 0x59, 0x0d, 0x3e, 0x8c, 0xf4, 0x9b, 0x26, 0x27, 0x21, 0x8f, + 0x0c, 0x29, 0x2f, 0xa6, 0x6a, 0xda, 0x94, 0x5f, 0xa5, 0x5b, 0xb2, 0x35, 0x48, 0xe3, + 0x3a, 0x83, 0xa5, 0x62, 0x95, 0x7a, 0x31, 0x49, 0xa9, 0x93, 0xcc, 0x47, 0x23, 0x62, + 0x29, 0x87, 0x36, 0xa8, 0xb7, 0x78, 0xd9, 0x7c, 0xe4, 0x23, 0x01, 0x3d, 0x64, 0xb3, + 0x2c, 0xd1, 0x72, 0xef, 0xa5, 0x51, 0xbf, 0x7f, 0x36, 0x8f, 0x04, 0xbd, 0xae, 0xc6, + 0x09, 0x1a, 0x30, 0x04, 0xa7, 0x57, 0x59, 0x8b, 0x80, 0x1d, 0xcf, 0x67, 0x5c, 0xb8, + 0x3e, 0x43, 0xa5, 0x3a, 0xe8, 0xb2, 0x54, 0xd3, 0x33, 0xbc, 0xda, 0x20, 0xd4, 0x81, + 0x7d, 0x34, 0x77, 0xab, 0xfb, 0xa2, 0x5b, 0xb8, 0x3d, 0xf5, 0x94, 0x9c, 0x12, 0x6f, + 0x14, 0x9b, 0x1d, 0x99, 0x34, 0x1e, 0x4e, 0x6f, + ], + c_enc: [ + 0xbf, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, + 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, + 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, + 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0x53, 0x14, 0xfa, 0x95, + 0x27, 0xae, 0xc5, 0xaf, 0xd5, 0x06, 0xc2, 0x42, 0xac, 0xdc, 0xa9, 0xd3, 0xc9, 0xa5, + 0x53, 0xcf, 0xef, 0x49, 0x9e, 0x87, 0x30, 0xf7, 0x55, 0x6a, 0xd0, 0xba, 0xc0, 0xff, + 0xb6, 0xd0, 0x8e, 0x7c, 0xac, 0x9b, 0x6e, 0x71, 0xf6, 0x6d, 0x19, 0x17, 0xfc, 0x52, + 0xdc, 0x91, 0x33, 0xae, 0x12, 0x4a, 0x40, 0x9d, 0xda, 0x38, 0x75, 0xcb, 0xae, 0xb5, + 0xf2, 0x96, 0xd5, 0x3a, 0x9f, 0x17, 0xb0, 0x28, 0x7d, 0xaa, 0x31, 0xd6, 0x89, 0xa7, + 0xde, 0xaf, 0x05, 0x2d, 0xab, 0xa6, 0xd0, 0xe8, 0x87, 0xcd, 0x1a, 0x3a, 0x6d, 0xd4, + 0x67, 0x17, 0xe5, 0xda, 0x63, 0xe5, 0x59, 0x67, 0x95, 0xf8, 0xe1, 0xdb, 0x6a, 0x45, + 0x8e, 0xab, 0x64, 0xa7, 0xd0, 0x68, 0xe1, 0x67, 0xef, 0xf1, 0x9b, 0xf2, 0x3b, 0x1b, + 0xe7, 0x72, 0x87, 0xf9, 0x0e, 0xe5, 0xcd, 0x34, 0x13, 0x85, 0xad, 0xc9, 0xda, 0xb7, + 0xd0, 0xef, 0x05, 0xc3, 0x61, 0x7d, 0x9f, 0x4b, 0xd7, 0xa2, 0x78, 0xb0, 0xa7, 0xc7, + 0x57, 0x73, 0x57, 0x89, 0xd3, 0xff, 0x0e, 0x91, 0xfb, 0xe1, 0x31, 0x78, 0xae, 0x76, + 0xeb, 0x91, 0xd8, 0x35, 0xd0, 0x65, 0xd7, 0xb3, 0x83, 0x18, 0xf5, 0x64, 0xb7, 0x69, + 0xe8, 0xd9, 0x68, 0x97, 0xb7, 0xab, 0xc8, 0xaa, 0xf3, 0x41, 0x7a, 0x49, 0xe6, 0x8f, + 0x35, 0xcd, 0x7f, 0x45, 0x1d, 0x99, 0x4a, 0xd8, 0x7d, 0xd4, 0xbc, 0x55, 0xc4, 0x5d, + 0xb3, 0x21, 0xf8, 0x49, 0xce, 0xb9, 0x54, 0x30, 0xe8, 0xe6, 0xe2, 0xe4, 0x8c, 0x3b, + 0xbf, 0x8f, 0x7a, 0x1a, 0xaf, 0x1c, 0x52, 0xf2, 0x3f, 0xca, 0x52, 0xca, 0xcc, 0xfb, + 0x26, 0xa4, 0x58, 0x40, 0x42, 0x73, 0xe5, 0x69, 0x7f, 0xcc, 0xf5, 0xa5, 0x9a, 0x61, + 0xb3, 0xea, 0xd6, 0x6a, 0x03, 0xfd, 0xaf, 0x31, 0xb2, 0xeb, 0x2d, 0x32, 0xa9, 0x02, + 0x40, 0x50, 0x98, 0xa7, 0x67, 0xbb, 0x6d, 0x30, 0xbf, 0x1b, 0x48, 0x7d, 0xcc, 0x5d, + 0x38, 0xfb, 0x9d, 0x54, 0x9c, 0xc5, 0x21, 0x30, 0x75, 0xe1, 0x2d, 0x04, 0x34, 0x71, + 0xc3, 0xab, 0x03, 0x5b, 0x1d, 0xff, 0xd6, 0xe8, 0xaa, 0x61, 0x99, 0xc8, 0x0c, 0xe9, + 0x9d, 0x66, 0xa5, 0x07, 0x3b, 0x91, 0x73, 0xc3, 0x25, 0x4b, 0xd2, 0x4a, 0xf5, 0x9c, + 0x96, 0x27, 0xb9, 0x8c, 0xdb, 0x06, 0x0f, 0x07, 0x34, 0x04, 0xb4, 0xfb, 0xf6, 0x5b, + 0xdd, 0x1a, 0xcb, 0x1c, 0xb6, 0xc0, 0xa4, 0xc1, 0x8d, 0x55, 0x4f, 0x7a, 0x4c, 0x5a, + 0x1a, 0x93, 0x94, 0xb3, 0x85, 0xe8, 0xdf, 0xf4, 0xbb, 0xd1, 0x4a, 0x1a, 0x20, 0x1f, + 0xa8, 0x33, 0x20, 0x37, 0x34, 0x5a, 0x62, 0x29, 0x3d, 0x8c, 0xfc, 0x5c, 0xd9, 0x4c, + 0x0c, 0x21, 0xa9, 0xc8, 0x06, 0x52, 0x1c, 0xe2, 0x28, 0x01, 0xdb, 0xa5, 0xb5, 0xa3, + 0xb3, 0xf6, 0x9a, 0xbd, 0x01, 0xd4, 0x4c, 0xcb, 0xc2, 0x3b, 0x06, 0x3f, 0x41, 0x2c, + 0xa1, 0xa9, 0xd4, 0xfd, 0x17, 0xda, 0xbe, 0x54, 0x9f, 0x8b, 0x89, 0x11, 0x21, 0xe0, + 0x79, 0xb8, 0x2b, 0x5e, 0x6e, 0xa7, 0x43, 0xe6, 0x37, 0xb9, 0xd2, 0xd1, 0x1e, 0x86, + 0xa0, 0xc2, 0x76, 0x9a, 0xe3, 0xdc, 0xde, 0xcd, 0x74, 0xcb, 0xec, 0xe5, 0x6e, 0x52, + 0x74, 0xca, 0x1f, 0x23, 0x25, 0xc3, 0x93, 0xe5, 0xef, 0x18, 0xef, 0x99, 0x03, 0x04, + 0x22, 0x39, 0xe2, 0x5c, 0x2f, 0x10, 0x62, 0x21, 0x2a, 0x04, 0x67, 0x0d, 0xd3, 0xea, + 0xd5, 0xa9, 0x55, 0xf7, 0x8b, 0x6a, 0x00, 0xdd, 0x9f, 0x12, 0xc1, 0xdc, 0x0b, 0x3a, + 0x58, 0xaf, 0x82, 0x3b, 0x78, 0x73, 0x22, 0xaa, 0x8f, 0x2e, 0xde, 0xc8, 0x48, 0x41, + 0x99, 0x15, 0xb0, 0x6b, 0x60, 0xd9, 0x5a, 0xf2, 0xd4, 0x41, 0xba, 0xd4, 0x35, 0x7b, + 0xed, 0x8a, 0xdb, 0xf0, 0xd0, 0x5f, 0xc6, 0x37, 0xcb, 0xaa, 0xff, 0x15, 0x58, 0x26, + 0x8c, 0x9c, 0x92, 0x41, 0x9e, 0x97, 0x51, 0xc4, 0x18, 0xa6, 0x7a, 0xe3, 0x86, 0x29, + 0xf0, 0xcd, 0xf7, 0x7d, 0xaa, 0xd6, 0xf0, 0xac, 0xc9, 0x32, 0x98, 0x51, 0xcd, 0x17, + 0xda, 0x6a, 0xd7, 0xbb, 0x73, 0xf3, 0x5d, 0x23, 0xba, 0xc7, + ], + ock: [ + 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, + 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, + 0x8e, 0x29, 0x42, 0xa3, + ], + op: [ + 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, + 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, + 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, + 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, + 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, + ], + c_out: [ + 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, + 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, + 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, + 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, + 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, + 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xc3, 0x7c, 0x7d, 0xbb, 0xe5, 0x51, 0xd9, 0xd3, 0xb1, 0xa4, 0x96, 0x88, 0x7d, 0xb2, + 0xe8, 0x42, 0xdc, 0x94, 0x52, 0x01, 0xf4, 0x08, 0x10, 0xdf, 0x4d, 0x76, 0x39, 0x32, + 0xed, 0x5c, 0x76, 0x39, 0x8b, 0x35, 0x73, 0xfe, 0x23, 0xf1, 0xe8, 0xb7, 0xe7, 0x9f, + 0x1c, 0x16, 0x95, 0xc0, 0x97, 0xc1, 0x24, 0xff, 0x1f, 0x7d, 0x6e, 0x61, 0xf2, 0xc5, + 0x8f, 0x14, 0x39, 0xa7, 0x56, 0x96, 0x9d, 0x19, + ], + ovk: [ + 0xa6, 0x68, 0xa0, 0xae, 0x2b, 0xb9, 0x34, 0xc8, 0x2c, 0x41, 0x42, 0xda, 0x69, 0xd1, + 0x2c, 0xa7, 0xde, 0x9a, 0x7d, 0xf7, 0x06, 0x40, 0x0e, 0xc7, 0x98, 0x78, 0xd8, 0x68, + 0xe1, 0x7e, 0x8f, 0x71, + ], + default_d: [ + 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, + ], + default_pk_d: [ + 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, + 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, + 0x6b, 0x80, 0xbb, 0xb7, + ], + v: 11137853725062838288, + rseed: [ + 0x25, 0x37, 0xb8, 0x71, 0xb4, 0x29, 0x4a, 0x65, 0xd3, 0xe0, 0x55, 0xff, 0x71, 0x8d, + 0xd9, 0xdc, 0x8c, 0x75, 0xe7, 0xe5, 0xb2, 0xef, 0xe4, 0x42, 0x63, 0x73, 0x71, 0xb7, + 0xc4, 0x8f, 0x6e, 0xe9, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x9e, 0x3e, 0xa3, 0x8a, 0x4b, 0x0f, 0x2f, 0x67, 0xfc, 0x2b, 0x90, 0x8c, 0xda, + 0x65, 0x7e, 0xae, 0x75, 0x4e, 0x03, 0x7e, 0x26, 0x2e, 0x9a, 0x9f, 0x9b, 0xd7, 0xec, + 0x42, 0x67, 0xed, 0x8e, 0x96, 0x93, 0x0e, 0x10, 0x84, 0x78, 0x3c, 0x37, 0xd6, 0xf9, + 0xdd, 0x15, 0xfd, 0x29, 0xf4, 0xcc, 0x47, 0x7e, 0x66, 0xf1, 0x30, 0xd6, 0x30, 0x43, + 0x0d, 0xcc, 0x01, 0x04, 0x89, 0x9b, 0x4f, 0x9f, 0x46, 0xeb, 0x09, 0x0e, 0xf7, 0xfc, + 0x90, 0xb4, 0x79, 0xab, 0xf6, 0x1f, 0x93, 0x95, 0x5e, 0xe0, 0x0e, 0x6a, 0x18, 0x48, + 0xf1, 0xab, 0x14, 0xad, 0x33, 0x4f, 0x2b, 0x68, 0x03, 0x58, 0x08, 0xcd, 0xf1, 0xbb, + 0x9e, 0x9d, 0x9a, 0x81, 0x6b, 0xaf, 0x72, 0x8a, 0x95, 0x5b, 0x96, 0x0b, 0x77, 0x01, + 0xfa, 0x62, 0x66, 0x87, 0xdc, 0x3c, 0x9c, 0xba, 0x64, 0x63, 0x37, 0xb5, 0x3e, 0x29, + 0x81, 0x6e, 0x94, 0x82, 0xdd, 0xf5, 0x57, 0x8a, 0x87, 0x68, 0xaa, 0xe4, 0x77, 0xfc, + 0xe4, 0x10, 0xac, 0x2d, 0x5d, 0xe6, 0x09, 0x58, 0x61, 0xc1, 0x11, 0xd7, 0xfe, 0xb3, + 0xe6, 0xbb, 0x4f, 0xbb, 0x5a, 0x54, 0x95, 0x54, 0x95, 0x97, 0x27, 0x98, 0x35, 0x0a, + 0x25, 0x3f, 0x05, 0xf6, 0x6c, 0x2e, 0xcf, 0xcb, 0xc0, 0xed, 0x43, 0xf5, 0xec, 0x2e, + 0x6d, 0x8d, 0xba, 0x15, 0xa5, 0x12, 0x54, 0xd9, 0x7b, 0x18, 0x21, 0x10, 0x7c, 0x07, + 0xdd, 0x9a, 0x16, 0xef, 0x84, 0x06, 0xf9, 0x43, 0xe2, 0x82, 0xb9, 0x5d, 0x4b, 0x36, + 0x25, 0x30, 0xc9, 0x13, 0xd6, 0xba, 0x42, 0x1d, 0xf6, 0x02, 0x7d, 0xe5, 0xaf, 0x1e, + 0x47, 0x45, 0xd5, 0x86, 0x81, 0x06, 0x95, 0x4b, 0xe6, 0xc1, 0x96, 0x27, 0x80, 0xa2, + 0x94, 0x10, 0x72, 0xe9, 0x51, 0x31, 0xb1, 0x67, 0x9d, 0xf0, 0x63, 0x76, 0x25, 0x04, + 0x2c, 0x37, 0xd4, 0x8f, 0xfb, 0x15, 0x2e, 0x5e, 0xbc, 0x18, 0x5c, 0x8a, 0x2b, 0x7d, + 0x43, 0x85, 0xf1, 0xc9, 0x5a, 0xf9, 0x37, 0xdf, 0x78, 0xdf, 0xd8, 0x75, 0x7f, 0xab, + 0x43, 0x49, 0x68, 0xb0, 0xb5, 0x7c, 0x66, 0x57, 0x44, 0x68, 0xf1, 0x60, 0xb4, 0x47, + 0xac, 0x82, 0x21, 0xe5, 0x06, 0x06, 0x76, 0xa8, 0x42, 0xa1, 0xc6, 0xb7, 0x17, 0x2d, + 0xd3, 0x34, 0x0f, 0x76, 0x40, 0x70, 0xab, 0x1f, 0xe0, 0x91, 0xc5, 0xc7, 0x4c, 0x95, + 0xa5, 0xdc, 0x04, 0x33, 0x90, 0x72, 0x3a, 0x4c, 0x12, 0x7d, 0xa1, 0x4c, 0xdd, 0xe1, + 0xdc, 0x26, 0x75, 0xa6, 0x23, 0x40, 0xb3, 0xe6, 0xaf, 0xd0, 0x52, 0x2a, 0x31, 0xde, + 0x26, 0xe7, 0xd1, 0xec, 0x3a, 0x9c, 0x8a, 0x09, 0x1f, 0xfd, 0xc7, 0x5b, 0x7e, 0xcf, + 0xdc, 0x7c, 0x12, 0x99, 0x5a, 0x5e, 0x37, 0xce, 0x34, 0x88, 0xbd, 0x29, 0xf8, 0x62, + 0x9d, 0x68, 0xf6, 0x96, 0x49, 0x24, 0x48, 0xdd, 0x52, 0x66, 0x97, 0x47, 0x6d, 0xc0, + 0x61, 0x34, 0x6e, 0xbe, 0x3f, 0x67, 0x72, 0x17, 0xff, 0x9c, 0x60, 0xef, 0xce, 0x94, + 0x3a, 0xf2, 0x8d, 0xfd, 0x3f, 0x9e, 0x59, 0x69, 0x25, 0x98, 0xa6, 0x04, 0x7c, 0x23, + 0xc4, 0xc0, 0x14, 0x00, 0xf1, 0xab, 0x57, 0x30, 0xea, 0xc0, 0xae, 0x8d, 0x58, 0x43, + 0xd5, 0x05, 0x1c, 0x37, 0x62, 0x40, 0x17, 0x2a, 0xf2, 0x18, 0xd7, 0xa1, 0xec, 0xfe, + 0x65, 0xb4, 0xf7, 0x51, 0x00, 0x63, 0x89, 0x83, 0xc1, 0x4d, 0xe4, 0x97, 0x47, 0x55, + 0xda, 0xde, 0x80, 0x18, 0xc9, 0xb8, 0xf4, 0x54, 0x3f, 0xb0, 0x95, 0x96, 0x15, 0x13, + 0xe6, 0x7c, 0x61, 0xdb, 0xc5, 0x9c, 0x60, 0x7f, 0x9b, 0x51, 0xf8, 0xd0, 0x9b, 0xdc, + 0xad, 0x28, 0xbc, 0xfb, 0x9e, 0x5d, 0x27, 0x44, 0xea, 0x88, 0x48, 0xb2, 0x62, 0x3a, + 0xc0, 0x7f, 0x8e, 0xf6, 0x1a, 0x81, 0xa3, 0x59, + ], + cv_net: [ + 0xb2, 0x7f, 0x48, 0x59, 0x15, 0x0d, 0x48, 0x45, 0xab, 0x57, 0x78, 0x82, 0x61, 0x50, + 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, + 0x88, 0xff, 0xee, 0x2f, + ], + nf_old: [ + 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, + 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, + 0x92, 0xd7, 0xa0, 0x24, + ], + cmx: [ + 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, + 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, + 0x67, 0xd4, 0x93, 0x0b, + ], + esk: [ + 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, + 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, + 0xc7, 0xda, 0x74, 0x36, + ], + ephemeral_key: [ + 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, + 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, + 0x23, 0x1a, 0x61, 0x34, + ], + shared_secret: [ + 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, + 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, + 0x3f, 0x5c, 0xc5, 0x37, + ], + k_enc: [ + 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, + 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, + 0xbe, 0x25, 0xe9, 0x8d, + ], + p_enc: [ + 0x03, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, + 0xa1, 0xba, 0xf3, 0x9a, 0x91, 0x9a, 0x25, 0x37, 0xb8, 0x71, 0xb4, 0x29, 0x4a, 0x65, + 0xd3, 0xe0, 0x55, 0xff, 0x71, 0x8d, 0xd9, 0xdc, 0x8c, 0x75, 0xe7, 0xe5, 0xb2, 0xef, + 0xe4, 0x42, 0x63, 0x73, 0x71, 0xb7, 0xc4, 0x8f, 0x6e, 0xe9, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x9e, 0x3e, 0xa3, 0x8a, 0x4b, 0x0f, 0x2f, 0x67, 0xfc, 0x2b, 0x90, 0x8c, 0xda, + 0x65, 0x7e, 0xae, 0x75, 0x4e, 0x03, 0x7e, 0x26, 0x2e, 0x9a, 0x9f, 0x9b, 0xd7, 0xec, + 0x42, 0x67, 0xed, 0x8e, 0x96, 0x93, 0x0e, 0x10, 0x84, 0x78, 0x3c, 0x37, 0xd6, 0xf9, + 0xdd, 0x15, 0xfd, 0x29, 0xf4, 0xcc, 0x47, 0x7e, 0x66, 0xf1, 0x30, 0xd6, 0x30, 0x43, + 0x0d, 0xcc, 0x01, 0x04, 0x89, 0x9b, 0x4f, 0x9f, 0x46, 0xeb, 0x09, 0x0e, 0xf7, 0xfc, + 0x90, 0xb4, 0x79, 0xab, 0xf6, 0x1f, 0x93, 0x95, 0x5e, 0xe0, 0x0e, 0x6a, 0x18, 0x48, + 0xf1, 0xab, 0x14, 0xad, 0x33, 0x4f, 0x2b, 0x68, 0x03, 0x58, 0x08, 0xcd, 0xf1, 0xbb, + 0x9e, 0x9d, 0x9a, 0x81, 0x6b, 0xaf, 0x72, 0x8a, 0x95, 0x5b, 0x96, 0x0b, 0x77, 0x01, + 0xfa, 0x62, 0x66, 0x87, 0xdc, 0x3c, 0x9c, 0xba, 0x64, 0x63, 0x37, 0xb5, 0x3e, 0x29, + 0x81, 0x6e, 0x94, 0x82, 0xdd, 0xf5, 0x57, 0x8a, 0x87, 0x68, 0xaa, 0xe4, 0x77, 0xfc, + 0xe4, 0x10, 0xac, 0x2d, 0x5d, 0xe6, 0x09, 0x58, 0x61, 0xc1, 0x11, 0xd7, 0xfe, 0xb3, + 0xe6, 0xbb, 0x4f, 0xbb, 0x5a, 0x54, 0x95, 0x54, 0x95, 0x97, 0x27, 0x98, 0x35, 0x0a, + 0x25, 0x3f, 0x05, 0xf6, 0x6c, 0x2e, 0xcf, 0xcb, 0xc0, 0xed, 0x43, 0xf5, 0xec, 0x2e, + 0x6d, 0x8d, 0xba, 0x15, 0xa5, 0x12, 0x54, 0xd9, 0x7b, 0x18, 0x21, 0x10, 0x7c, 0x07, + 0xdd, 0x9a, 0x16, 0xef, 0x84, 0x06, 0xf9, 0x43, 0xe2, 0x82, 0xb9, 0x5d, 0x4b, 0x36, + 0x25, 0x30, 0xc9, 0x13, 0xd6, 0xba, 0x42, 0x1d, 0xf6, 0x02, 0x7d, 0xe5, 0xaf, 0x1e, + 0x47, 0x45, 0xd5, 0x86, 0x81, 0x06, 0x95, 0x4b, 0xe6, 0xc1, 0x96, 0x27, 0x80, 0xa2, + 0x94, 0x10, 0x72, 0xe9, 0x51, 0x31, 0xb1, 0x67, 0x9d, 0xf0, 0x63, 0x76, 0x25, 0x04, + 0x2c, 0x37, 0xd4, 0x8f, 0xfb, 0x15, 0x2e, 0x5e, 0xbc, 0x18, 0x5c, 0x8a, 0x2b, 0x7d, + 0x43, 0x85, 0xf1, 0xc9, 0x5a, 0xf9, 0x37, 0xdf, 0x78, 0xdf, 0xd8, 0x75, 0x7f, 0xab, + 0x43, 0x49, 0x68, 0xb0, 0xb5, 0x7c, 0x66, 0x57, 0x44, 0x68, 0xf1, 0x60, 0xb4, 0x47, + 0xac, 0x82, 0x21, 0xe5, 0x06, 0x06, 0x76, 0xa8, 0x42, 0xa1, 0xc6, 0xb7, 0x17, 0x2d, + 0xd3, 0x34, 0x0f, 0x76, 0x40, 0x70, 0xab, 0x1f, 0xe0, 0x91, 0xc5, 0xc7, 0x4c, 0x95, + 0xa5, 0xdc, 0x04, 0x33, 0x90, 0x72, 0x3a, 0x4c, 0x12, 0x7d, 0xa1, 0x4c, 0xdd, 0xe1, + 0xdc, 0x26, 0x75, 0xa6, 0x23, 0x40, 0xb3, 0xe6, 0xaf, 0xd0, 0x52, 0x2a, 0x31, 0xde, + 0x26, 0xe7, 0xd1, 0xec, 0x3a, 0x9c, 0x8a, 0x09, 0x1f, 0xfd, 0xc7, 0x5b, 0x7e, 0xcf, + 0xdc, 0x7c, 0x12, 0x99, 0x5a, 0x5e, 0x37, 0xce, 0x34, 0x88, 0xbd, 0x29, 0xf8, 0x62, + 0x9d, 0x68, 0xf6, 0x96, 0x49, 0x24, 0x48, 0xdd, 0x52, 0x66, 0x97, 0x47, 0x6d, 0xc0, + 0x61, 0x34, 0x6e, 0xbe, 0x3f, 0x67, 0x72, 0x17, 0xff, 0x9c, 0x60, 0xef, 0xce, 0x94, + 0x3a, 0xf2, 0x8d, 0xfd, 0x3f, 0x9e, 0x59, 0x69, 0x25, 0x98, 0xa6, 0x04, 0x7c, 0x23, + 0xc4, 0xc0, 0x14, 0x00, 0xf1, 0xab, 0x57, 0x30, 0xea, 0xc0, 0xae, 0x8d, 0x58, 0x43, + 0xd5, 0x05, 0x1c, 0x37, 0x62, 0x40, 0x17, 0x2a, 0xf2, 0x18, 0xd7, 0xa1, 0xec, 0xfe, + 0x65, 0xb4, 0xf7, 0x51, 0x00, 0x63, 0x89, 0x83, 0xc1, 0x4d, 0xe4, 0x97, 0x47, 0x55, + 0xda, 0xde, 0x80, 0x18, 0xc9, 0xb8, 0xf4, 0x54, 0x3f, 0xb0, 0x95, 0x96, 0x15, 0x13, + 0xe6, 0x7c, 0x61, 0xdb, 0xc5, 0x9c, 0x60, 0x7f, 0x9b, 0x51, 0xf8, 0xd0, 0x9b, 0xdc, + 0xad, 0x28, 0xbc, 0xfb, 0x9e, 0x5d, 0x27, 0x44, 0xea, 0x88, 0x48, 0xb2, 0x62, 0x3a, + 0xc0, 0x7f, 0x8e, 0xf6, 0x1a, 0x81, 0xa3, 0x59, + ], + c_enc: [ + 0x76, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, + 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, + 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, + 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0xc9, 0xb7, 0x31, 0x44, + 0x93, 0x2b, 0x1e, 0xeb, 0x8c, 0x2a, 0x84, 0xf9, 0x3d, 0x9b, 0xdf, 0x53, 0x78, 0x67, + 0xab, 0x82, 0x4c, 0xc3, 0xa4, 0xc5, 0xdc, 0x5b, 0xeb, 0xd8, 0x95, 0x26, 0xba, 0x5c, + 0x2b, 0x5a, 0x76, 0x76, 0x4b, 0x33, 0x2f, 0x2d, 0xdc, 0x0f, 0x48, 0x2f, 0xd4, 0x57, + 0xb3, 0x6d, 0x16, 0x05, 0xca, 0xea, 0xe2, 0xc7, 0xf1, 0x5a, 0x05, 0x91, 0xfa, 0x40, + 0xa4, 0x57, 0x49, 0xa7, 0x58, 0xcb, 0x88, 0xaa, 0xd5, 0xd0, 0x85, 0x92, 0x11, 0x4e, + 0x75, 0x7b, 0x19, 0x37, 0xf4, 0x99, 0x73, 0xe5, 0xba, 0x72, 0x8c, 0xa4, 0xb0, 0x9c, + 0x71, 0xe2, 0x25, 0x54, 0xf8, 0x89, 0x34, 0x8d, 0xbe, 0x7b, 0x7d, 0x7b, 0xd5, 0x02, + 0x84, 0x71, 0x20, 0xe1, 0xfe, 0xb6, 0xaf, 0x86, 0xeb, 0x19, 0x1a, 0xb2, 0x1d, 0x21, + 0x20, 0xa6, 0xbd, 0x2c, 0x38, 0x04, 0x22, 0x28, 0xa7, 0xb0, 0xda, 0xc3, 0x16, 0xe3, + 0x39, 0x05, 0x4f, 0xb4, 0x30, 0xce, 0xac, 0x6c, 0xea, 0xa8, 0xd3, 0x18, 0x10, 0xa7, + 0x99, 0x7f, 0xfb, 0xc1, 0x58, 0xfc, 0x7b, 0x2c, 0xb6, 0x2b, 0x13, 0x5e, 0xde, 0x3f, + 0x65, 0x6e, 0x4b, 0x13, 0x57, 0xac, 0x31, 0x48, 0x96, 0xf1, 0x35, 0x58, 0xec, 0x32, + 0x90, 0x8e, 0x9d, 0xd6, 0x85, 0xb4, 0xee, 0x9a, 0x7d, 0x81, 0x4d, 0xdc, 0x50, 0x2c, + 0xe7, 0xac, 0xa1, 0xda, 0x00, 0xee, 0xda, 0xe4, 0x96, 0x03, 0x35, 0xe5, 0x75, 0x6a, + 0x42, 0xd6, 0xf4, 0x4f, 0x85, 0x2c, 0x8a, 0x7a, 0xd0, 0x0e, 0xf7, 0x9a, 0x4d, 0xb1, + 0x4e, 0xae, 0xc9, 0x56, 0x2a, 0xba, 0xc3, 0x08, 0x01, 0x1e, 0xbf, 0x00, 0x57, 0x6e, + 0x6c, 0xa3, 0xea, 0x16, 0xe5, 0x01, 0xbf, 0x35, 0x0f, 0x82, 0x14, 0xb6, 0x84, 0x04, + 0xdb, 0x24, 0x2e, 0x9f, 0x85, 0x3d, 0x82, 0xbe, 0x44, 0x25, 0x0d, 0xf0, 0xa8, 0x1d, + 0xe7, 0x0e, 0x10, 0x40, 0xfa, 0xde, 0x44, 0x69, 0x1e, 0xca, 0x6e, 0x03, 0xc4, 0x6c, + 0x4b, 0x57, 0xc7, 0x89, 0xc9, 0x74, 0x8e, 0x0e, 0x2e, 0xf4, 0x11, 0x9d, 0xbd, 0x7b, + 0x39, 0x3d, 0x63, 0x3c, 0x6e, 0xc8, 0xf0, 0xd0, 0x4d, 0x97, 0x1d, 0x2b, 0xd5, 0xab, + 0xed, 0x9f, 0x36, 0xc9, 0xb4, 0xb4, 0x6e, 0x3b, 0x32, 0x56, 0x9d, 0x31, 0x89, 0x45, + 0x6e, 0x65, 0x51, 0x67, 0x7e, 0xe7, 0x71, 0xb0, 0xf0, 0xa2, 0x6f, 0x84, 0xc2, 0x9f, + 0xdc, 0xa3, 0xd6, 0x42, 0x82, 0x60, 0x05, 0x37, 0x34, 0x7b, 0xd7, 0xf6, 0x0c, 0xe4, + 0x27, 0xbf, 0x55, 0xe9, 0xb1, 0xbf, 0xd4, 0xb7, 0x56, 0x4f, 0x9f, 0xb1, 0x93, 0x02, + 0xdc, 0x41, 0xe7, 0xde, 0xde, 0x7f, 0x4f, 0xc0, 0x0f, 0x57, 0x3e, 0x33, 0xf4, 0xbe, + 0x41, 0x40, 0xdd, 0xc9, 0x76, 0x93, 0xaf, 0x52, 0x48, 0x95, 0x87, 0xf0, 0xd0, 0x81, + 0x0f, 0x3d, 0x9c, 0x35, 0x6f, 0x32, 0xe9, 0x3d, 0x47, 0x56, 0x0c, 0x01, 0x1c, 0x0c, + 0x94, 0xe1, 0xa6, 0x49, 0x7e, 0x87, 0x45, 0x8e, 0xad, 0x8a, 0x34, 0x67, 0x84, 0xbc, + 0x42, 0x66, 0x16, 0x7f, 0x87, 0x7e, 0x38, 0x92, 0xa8, 0x98, 0x77, 0x4c, 0xe3, 0xad, + 0x3b, 0x82, 0x8d, 0x9d, 0xd1, 0xd2, 0xe4, 0x0a, 0x89, 0xf1, 0xfc, 0xe4, 0x9d, 0x6b, + 0x20, 0x18, 0x9e, 0x0c, 0x22, 0xe0, 0x17, 0xab, 0x55, 0x5b, 0x68, 0xa7, 0x4e, 0x66, + 0xb4, 0xeb, 0x31, 0xee, 0x78, 0xaf, 0xbe, 0x63, 0x25, 0xcb, 0xad, 0xd5, 0xa8, 0x38, + 0x29, 0x49, 0xf3, 0xc7, 0x48, 0xa9, 0xe7, 0x22, 0xfc, 0x58, 0xeb, 0xab, 0xdc, 0x69, + 0x64, 0x22, 0x4c, 0x48, 0x58, 0x6e, 0x94, 0x3c, 0x60, 0x2f, 0x70, 0x5e, 0x55, 0x4b, + 0xc0, 0x1c, 0x58, 0x90, 0x4d, 0x2f, 0xa7, 0x1e, 0x4c, 0x44, 0xe3, 0x8c, 0x3d, 0x19, + 0x04, 0x7d, 0xa9, 0x39, 0xaf, 0x3b, 0x3f, 0xba, 0x89, 0xad, 0x1b, 0x83, 0xb5, 0xb3, + 0xb4, 0xbd, 0x8c, 0xe5, 0x99, 0xeb, 0x69, 0x7a, 0xb6, 0x5d, 0x37, 0x04, 0x5e, 0xa9, + 0x15, 0x98, 0xdb, 0x59, 0x18, 0x75, 0xf6, 0xcc, 0x18, 0x02, 0x79, 0x0a, 0x3c, 0x1f, + 0x40, 0xeb, 0x68, 0x8e, 0x7c, 0xb8, 0xbb, 0x3d, 0x07, 0xde, + ], + ock: [ + 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, + 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, + 0x81, 0xf0, 0x8c, 0xfb, + ], + op: [ + 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, + 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, + 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, + 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, + 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, + ], + c_out: [ + 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, + 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, + 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, + 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, + 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, + 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x74, 0xa8, 0x41, 0x1a, 0x20, 0xbc, 0x3c, 0x53, 0xf7, 0xe7, 0xab, 0xb9, 0x31, 0x6c, + 0x44, 0x2b, 0x4b, 0x09, 0xcf, 0x88, 0xbb, 0xed, 0x4a, 0x90, 0xb9, 0x2f, 0x5a, 0x1c, + 0xed, 0x93, 0x16, 0x2b, 0xc3, 0x37, 0x34, 0x67, 0x20, 0xec, 0x0c, 0xd0, 0xea, 0x73, + 0x5d, 0x9e, 0x32, 0x3f, 0x20, 0xdb, 0x77, 0x8a, 0xd1, 0x8a, 0x84, 0xc7, 0x9e, 0xe6, + 0x28, 0x77, 0x99, 0xef, 0x02, 0x76, 0x41, 0x07, + ], + ovk: [ + 0x0c, 0x81, 0x1e, 0x4c, 0x31, 0xfb, 0xb4, 0x9f, 0x3a, 0x90, 0xbb, 0xd0, 0x5d, 0xce, + 0x62, 0xf3, 0x44, 0xe7, 0x07, 0x75, 0x93, 0x15, 0x9a, 0xe3, 0x50, 0x50, 0xb0, 0x4c, + 0x9e, 0x6b, 0x86, 0xbc, + ], + default_d: [ + 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, + ], + default_pk_d: [ + 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, + 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, + 0x17, 0x5b, 0xa9, 0x8b, + ], + v: 7387862906040043846, + rseed: [ + 0x25, 0x01, 0xe5, 0x1b, 0x01, 0x2a, 0xea, 0x94, 0x46, 0xa2, 0x10, 0x4e, 0x93, 0xf8, + 0x15, 0xa0, 0xb3, 0xa2, 0x9b, 0x45, 0x83, 0x14, 0xf3, 0xd8, 0xbe, 0x2b, 0x98, 0x23, + 0xd3, 0x42, 0xf4, 0x62, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x13, 0xe9, 0x42, 0xa7, 0xe1, 0x9a, 0x46, 0xe9, 0x70, 0xb5, 0xc5, 0x06, 0x70, + 0x84, 0x30, 0x31, 0x7b, 0x1b, 0xb3, 0xb3, 0x5d, 0xf6, 0x8a, 0xe3, 0x3a, 0x49, 0x26, + 0xa0, 0x3e, 0x6b, 0xfe, 0xb5, 0x51, 0x04, 0x16, 0xfc, 0xbb, 0x05, 0x24, 0xc9, 0xca, + 0x50, 0x74, 0x15, 0x6c, 0xc5, 0xa5, 0xd6, 0xfe, 0x1c, 0x99, 0x5e, 0xdc, 0x60, 0xa2, + 0xf5, 0x50, 0x41, 0x1a, 0xa4, 0x1e, 0x3d, 0xa3, 0xbd, 0xcf, 0x64, 0xbc, 0xf0, 0x4a, + 0x05, 0x10, 0x57, 0x1b, 0x93, 0x6d, 0x47, 0xe5, 0x5c, 0xec, 0x03, 0x30, 0xee, 0x8d, + 0xfe, 0x73, 0x56, 0x34, 0x04, 0xf0, 0x47, 0xd7, 0xf3, 0xa8, 0xa3, 0xd7, 0x74, 0x3b, + 0xc5, 0x54, 0x95, 0x52, 0x10, 0xf1, 0xeb, 0x0d, 0x08, 0x59, 0x9e, 0xa7, 0x7d, 0x5f, + 0x97, 0x4d, 0x87, 0x17, 0x6d, 0x37, 0xd9, 0x8b, 0x9c, 0x0a, 0xd4, 0x40, 0x40, 0x72, + 0x09, 0xed, 0x6a, 0x9f, 0x08, 0x46, 0x4d, 0x56, 0x55, 0x93, 0xe1, 0xa6, 0x3b, 0x93, + 0x85, 0x36, 0xb4, 0x92, 0x44, 0xe9, 0x7d, 0x88, 0x01, 0x73, 0xb6, 0x40, 0xf2, 0xdd, + 0xb7, 0x4d, 0x06, 0x8e, 0xcb, 0x46, 0xcf, 0x28, 0x9b, 0x7d, 0x89, 0x13, 0x07, 0xbb, + 0xa3, 0x70, 0x54, 0xcf, 0x91, 0xb3, 0x1f, 0xc8, 0x2f, 0x74, 0xd5, 0xfc, 0xc0, 0x00, + 0x94, 0x2e, 0xde, 0x91, 0x18, 0x25, 0xf5, 0x3f, 0xe6, 0x09, 0x68, 0x6f, 0x46, 0x32, + 0x23, 0xb1, 0xe9, 0xbc, 0x03, 0xbd, 0xe8, 0x95, 0xd1, 0x23, 0x8f, 0xad, 0x04, 0xa3, + 0xbf, 0xce, 0x68, 0xa0, 0x75, 0xe8, 0xa3, 0x7c, 0x0e, 0x87, 0xbf, 0x46, 0xdd, 0x01, + 0x55, 0x45, 0xf9, 0xb4, 0xfb, 0x0e, 0xec, 0x64, 0x5f, 0xfc, 0xbb, 0xe0, 0xca, 0x5f, + 0x8c, 0x56, 0x1b, 0x25, 0x7d, 0x52, 0xd6, 0x02, 0xd8, 0xc9, 0x4c, 0x50, 0x28, 0x73, + 0xa0, 0x1d, 0x92, 0x51, 0xd8, 0xc8, 0x60, 0xc0, 0x41, 0x52, 0x5b, 0x3b, 0xf4, 0xe3, + 0xa2, 0xeb, 0x92, 0x72, 0x81, 0x5c, 0x75, 0x86, 0x76, 0x84, 0x28, 0xb4, 0xc2, 0xb2, + 0x5e, 0x37, 0x45, 0xf0, 0x09, 0xc5, 0xdc, 0xe2, 0x0b, 0x69, 0xd5, 0xd7, 0xc4, 0x3c, + 0xeb, 0x73, 0x6b, 0x68, 0x31, 0xe8, 0xc1, 0x10, 0xf1, 0x6c, 0xfd, 0xb3, 0xa4, 0x67, + 0xe9, 0x41, 0x4c, 0x00, 0xec, 0xf1, 0x37, 0x31, 0x50, 0x08, 0x94, 0x55, 0x56, 0x78, + 0xc4, 0x97, 0xfa, 0xba, 0x9a, 0x95, 0xd0, 0x1c, 0xc4, 0x64, 0x39, 0x0f, 0xc4, 0xa7, + 0x6b, 0xfa, 0x8b, 0x0e, 0x1c, 0x68, 0xa5, 0x25, 0xd7, 0x06, 0xd6, 0x60, 0x4b, 0x23, + 0x30, 0xb6, 0xb3, 0x48, 0x52, 0x15, 0xf6, 0x06, 0xf1, 0x88, 0x3a, 0x75, 0x15, 0x88, + 0xc7, 0xef, 0xa5, 0x06, 0xc3, 0xe8, 0xd0, 0xc6, 0x01, 0x92, 0xe8, 0x47, 0x6b, 0xd1, + 0x17, 0x5d, 0x95, 0x62, 0x08, 0x7b, 0xdb, 0x81, 0x8e, 0x66, 0x21, 0x62, 0x86, 0xba, + 0xfe, 0x47, 0xff, 0x4d, 0xbc, 0xce, 0xd5, 0x14, 0x44, 0x48, 0x0a, 0x9a, 0x56, 0x73, + 0xec, 0xe7, 0xfa, 0xc7, 0x3a, 0x0e, 0xd4, 0x1a, 0xb0, 0x05, 0x17, 0x53, 0xa7, 0xca, + 0xa8, 0x9b, 0xe3, 0x13, 0x9a, 0xfd, 0x97, 0x93, 0xb3, 0xe0, 0x2f, 0x27, 0xf0, 0x40, + 0x04, 0x65, 0x95, 0xac, 0xd4, 0x7b, 0xf1, 0x3f, 0xd0, 0xda, 0x27, 0xf0, 0x9e, 0xda, + 0x48, 0x03, 0x6d, 0x3e, 0xe4, 0x37, 0xf2, 0xee, 0x8f, 0x86, 0x06, 0xea, 0x97, 0x34, + 0x3c, 0x33, 0x58, 0x46, 0x57, 0xf4, 0x6d, 0xba, 0x99, 0xdb, 0x5c, 0xfe, 0x6c, 0xa1, + 0x76, 0xfa, 0xb7, 0xb0, 0xf3, 0xbf, 0xa0, 0xab, 0x61, 0xe3, 0x40, 0xc3, 0x4e, 0xb9, + 0xf1, 0x7c, 0x7e, 0xc2, 0xbe, 0x03, 0xb1, 0x80, 0xf0, 0xbb, 0x6f, 0x43, 0x4c, 0x2a, + 0x65, 0x42, 0xe0, 0x0e, 0x84, 0x37, 0x3f, 0x4f, + ], + cv_net: [ + 0x47, 0x35, 0xa6, 0xfd, 0x21, 0x5c, 0x7b, 0x95, 0x03, 0x3d, 0xab, 0x62, 0xcc, 0xf9, + 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, + 0xe2, 0x3c, 0x39, 0x11, + ], + nf_old: [ + 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, + 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, + 0x3e, 0xe8, 0xed, 0x20, + ], + cmx: [ + 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, + 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, + 0x32, 0x4a, 0xe9, 0x04, + ], + esk: [ + 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, + 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, + 0x99, 0x07, 0xea, 0x0c, + ], + ephemeral_key: [ + 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, + 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, + 0x05, 0xc0, 0x61, 0x23, + ], + shared_secret: [ + 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, + 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, + 0x98, 0xa0, 0xd0, 0x00, + ], + k_enc: [ + 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, + 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, + 0x40, 0x8c, 0x2e, 0xfe, + ], + p_enc: [ + 0x03, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, + 0xcd, 0xa3, 0x2b, 0xf6, 0x86, 0x66, 0x25, 0x01, 0xe5, 0x1b, 0x01, 0x2a, 0xea, 0x94, + 0x46, 0xa2, 0x10, 0x4e, 0x93, 0xf8, 0x15, 0xa0, 0xb3, 0xa2, 0x9b, 0x45, 0x83, 0x14, + 0xf3, 0xd8, 0xbe, 0x2b, 0x98, 0x23, 0xd3, 0x42, 0xf4, 0x62, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x13, 0xe9, 0x42, 0xa7, 0xe1, 0x9a, 0x46, 0xe9, 0x70, 0xb5, 0xc5, 0x06, 0x70, + 0x84, 0x30, 0x31, 0x7b, 0x1b, 0xb3, 0xb3, 0x5d, 0xf6, 0x8a, 0xe3, 0x3a, 0x49, 0x26, + 0xa0, 0x3e, 0x6b, 0xfe, 0xb5, 0x51, 0x04, 0x16, 0xfc, 0xbb, 0x05, 0x24, 0xc9, 0xca, + 0x50, 0x74, 0x15, 0x6c, 0xc5, 0xa5, 0xd6, 0xfe, 0x1c, 0x99, 0x5e, 0xdc, 0x60, 0xa2, + 0xf5, 0x50, 0x41, 0x1a, 0xa4, 0x1e, 0x3d, 0xa3, 0xbd, 0xcf, 0x64, 0xbc, 0xf0, 0x4a, + 0x05, 0x10, 0x57, 0x1b, 0x93, 0x6d, 0x47, 0xe5, 0x5c, 0xec, 0x03, 0x30, 0xee, 0x8d, + 0xfe, 0x73, 0x56, 0x34, 0x04, 0xf0, 0x47, 0xd7, 0xf3, 0xa8, 0xa3, 0xd7, 0x74, 0x3b, + 0xc5, 0x54, 0x95, 0x52, 0x10, 0xf1, 0xeb, 0x0d, 0x08, 0x59, 0x9e, 0xa7, 0x7d, 0x5f, + 0x97, 0x4d, 0x87, 0x17, 0x6d, 0x37, 0xd9, 0x8b, 0x9c, 0x0a, 0xd4, 0x40, 0x40, 0x72, + 0x09, 0xed, 0x6a, 0x9f, 0x08, 0x46, 0x4d, 0x56, 0x55, 0x93, 0xe1, 0xa6, 0x3b, 0x93, + 0x85, 0x36, 0xb4, 0x92, 0x44, 0xe9, 0x7d, 0x88, 0x01, 0x73, 0xb6, 0x40, 0xf2, 0xdd, + 0xb7, 0x4d, 0x06, 0x8e, 0xcb, 0x46, 0xcf, 0x28, 0x9b, 0x7d, 0x89, 0x13, 0x07, 0xbb, + 0xa3, 0x70, 0x54, 0xcf, 0x91, 0xb3, 0x1f, 0xc8, 0x2f, 0x74, 0xd5, 0xfc, 0xc0, 0x00, + 0x94, 0x2e, 0xde, 0x91, 0x18, 0x25, 0xf5, 0x3f, 0xe6, 0x09, 0x68, 0x6f, 0x46, 0x32, + 0x23, 0xb1, 0xe9, 0xbc, 0x03, 0xbd, 0xe8, 0x95, 0xd1, 0x23, 0x8f, 0xad, 0x04, 0xa3, + 0xbf, 0xce, 0x68, 0xa0, 0x75, 0xe8, 0xa3, 0x7c, 0x0e, 0x87, 0xbf, 0x46, 0xdd, 0x01, + 0x55, 0x45, 0xf9, 0xb4, 0xfb, 0x0e, 0xec, 0x64, 0x5f, 0xfc, 0xbb, 0xe0, 0xca, 0x5f, + 0x8c, 0x56, 0x1b, 0x25, 0x7d, 0x52, 0xd6, 0x02, 0xd8, 0xc9, 0x4c, 0x50, 0x28, 0x73, + 0xa0, 0x1d, 0x92, 0x51, 0xd8, 0xc8, 0x60, 0xc0, 0x41, 0x52, 0x5b, 0x3b, 0xf4, 0xe3, + 0xa2, 0xeb, 0x92, 0x72, 0x81, 0x5c, 0x75, 0x86, 0x76, 0x84, 0x28, 0xb4, 0xc2, 0xb2, + 0x5e, 0x37, 0x45, 0xf0, 0x09, 0xc5, 0xdc, 0xe2, 0x0b, 0x69, 0xd5, 0xd7, 0xc4, 0x3c, + 0xeb, 0x73, 0x6b, 0x68, 0x31, 0xe8, 0xc1, 0x10, 0xf1, 0x6c, 0xfd, 0xb3, 0xa4, 0x67, + 0xe9, 0x41, 0x4c, 0x00, 0xec, 0xf1, 0x37, 0x31, 0x50, 0x08, 0x94, 0x55, 0x56, 0x78, + 0xc4, 0x97, 0xfa, 0xba, 0x9a, 0x95, 0xd0, 0x1c, 0xc4, 0x64, 0x39, 0x0f, 0xc4, 0xa7, + 0x6b, 0xfa, 0x8b, 0x0e, 0x1c, 0x68, 0xa5, 0x25, 0xd7, 0x06, 0xd6, 0x60, 0x4b, 0x23, + 0x30, 0xb6, 0xb3, 0x48, 0x52, 0x15, 0xf6, 0x06, 0xf1, 0x88, 0x3a, 0x75, 0x15, 0x88, + 0xc7, 0xef, 0xa5, 0x06, 0xc3, 0xe8, 0xd0, 0xc6, 0x01, 0x92, 0xe8, 0x47, 0x6b, 0xd1, + 0x17, 0x5d, 0x95, 0x62, 0x08, 0x7b, 0xdb, 0x81, 0x8e, 0x66, 0x21, 0x62, 0x86, 0xba, + 0xfe, 0x47, 0xff, 0x4d, 0xbc, 0xce, 0xd5, 0x14, 0x44, 0x48, 0x0a, 0x9a, 0x56, 0x73, + 0xec, 0xe7, 0xfa, 0xc7, 0x3a, 0x0e, 0xd4, 0x1a, 0xb0, 0x05, 0x17, 0x53, 0xa7, 0xca, + 0xa8, 0x9b, 0xe3, 0x13, 0x9a, 0xfd, 0x97, 0x93, 0xb3, 0xe0, 0x2f, 0x27, 0xf0, 0x40, + 0x04, 0x65, 0x95, 0xac, 0xd4, 0x7b, 0xf1, 0x3f, 0xd0, 0xda, 0x27, 0xf0, 0x9e, 0xda, + 0x48, 0x03, 0x6d, 0x3e, 0xe4, 0x37, 0xf2, 0xee, 0x8f, 0x86, 0x06, 0xea, 0x97, 0x34, + 0x3c, 0x33, 0x58, 0x46, 0x57, 0xf4, 0x6d, 0xba, 0x99, 0xdb, 0x5c, 0xfe, 0x6c, 0xa1, + 0x76, 0xfa, 0xb7, 0xb0, 0xf3, 0xbf, 0xa0, 0xab, 0x61, 0xe3, 0x40, 0xc3, 0x4e, 0xb9, + 0xf1, 0x7c, 0x7e, 0xc2, 0xbe, 0x03, 0xb1, 0x80, 0xf0, 0xbb, 0x6f, 0x43, 0x4c, 0x2a, + 0x65, 0x42, 0xe0, 0x0e, 0x84, 0x37, 0x3f, 0x4f, + ], + c_enc: [ + 0x2c, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, + 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, + 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, + 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0x5d, 0xf4, 0x7c, 0x42, + 0xbd, 0x4e, 0xe2, 0x7d, 0xa0, 0xd6, 0xf9, 0x5a, 0xa4, 0xf1, 0x10, 0xd4, 0x5a, 0xe2, + 0x8e, 0x6f, 0xea, 0x40, 0xe4, 0x7b, 0xc6, 0x08, 0x1b, 0x78, 0xe2, 0xcb, 0xa1, 0x78, + 0xf5, 0x3b, 0x2c, 0x0f, 0xfd, 0x71, 0xf1, 0x52, 0x54, 0x55, 0x70, 0x8a, 0x92, 0x50, + 0xb0, 0x28, 0x17, 0x90, 0x70, 0xc7, 0xd3, 0xbe, 0x38, 0xdc, 0x67, 0x3f, 0xc1, 0x20, + 0x6c, 0xce, 0x64, 0xd5, 0x13, 0xed, 0x14, 0x3e, 0xbf, 0x45, 0x76, 0x3c, 0xa5, 0xea, + 0x12, 0x6e, 0xc1, 0x4d, 0x01, 0xda, 0xcb, 0x64, 0x60, 0xa5, 0xdc, 0xd2, 0x26, 0xd1, + 0xa9, 0x5c, 0x8d, 0xf9, 0xc4, 0x64, 0xd9, 0x35, 0xb6, 0xaa, 0x60, 0x7f, 0xff, 0x2d, + 0x3d, 0x72, 0x55, 0x83, 0xf8, 0x82, 0x1a, 0xe9, 0xb4, 0x7f, 0xce, 0x87, 0x5e, 0xa8, + 0x7c, 0xea, 0x41, 0x21, 0xec, 0xc8, 0x5b, 0x93, 0xa6, 0x38, 0xf5, 0x6f, 0x48, 0xf7, + 0x0a, 0xc8, 0x85, 0xb4, 0x89, 0x03, 0x02, 0xdf, 0x12, 0x5f, 0x80, 0x20, 0x16, 0x4d, + 0xd0, 0x13, 0xc7, 0x3f, 0xd2, 0xb4, 0x0f, 0x38, 0xc6, 0x9b, 0xe8, 0xcf, 0x0a, 0x3b, + 0xaf, 0xa6, 0x3b, 0x2b, 0xa0, 0x4d, 0x98, 0x65, 0xa2, 0x55, 0xc2, 0x34, 0x60, 0x83, + 0x33, 0x04, 0xf6, 0xe7, 0xf6, 0xec, 0xd4, 0x7d, 0xa7, 0x8b, 0x29, 0xfa, 0x95, 0x15, + 0xba, 0x60, 0xed, 0x15, 0x78, 0x78, 0x02, 0xe7, 0xa9, 0xf6, 0x63, 0xe9, 0xad, 0xda, + 0x54, 0x64, 0x77, 0xf7, 0xa9, 0x94, 0xc1, 0x6b, 0x81, 0x41, 0xf4, 0x54, 0xc4, 0x34, + 0xd5, 0x7f, 0x8b, 0xd3, 0xb8, 0xc0, 0xe7, 0x21, 0x1c, 0x91, 0x5f, 0xc3, 0xfe, 0xb5, + 0xdd, 0xe3, 0xb9, 0x1c, 0xed, 0x14, 0x93, 0x7a, 0x00, 0xff, 0xfc, 0xba, 0x37, 0x2e, + 0x69, 0x28, 0x70, 0xca, 0x44, 0xd0, 0x0c, 0x24, 0xc0, 0x0d, 0x61, 0x0a, 0x75, 0xa5, + 0x18, 0xca, 0x83, 0x62, 0xcd, 0xb3, 0xcf, 0xb6, 0xdc, 0x10, 0x5a, 0xa6, 0x86, 0x37, + 0x69, 0x52, 0x03, 0x45, 0xae, 0x51, 0x3d, 0x60, 0x89, 0x85, 0xba, 0x9b, 0xab, 0x2f, + 0x61, 0x4c, 0xd8, 0xad, 0xfc, 0xe6, 0x07, 0x15, 0x6d, 0x04, 0xe7, 0x70, 0xe6, 0x3e, + 0x2c, 0xd4, 0x7a, 0xb8, 0x5f, 0x8e, 0x74, 0x51, 0x8e, 0x19, 0x70, 0x7d, 0x83, 0xe3, + 0xc4, 0x86, 0xad, 0x9e, 0x0a, 0x28, 0x34, 0xc5, 0x8b, 0x4b, 0x72, 0x7a, 0x9b, 0xb0, + 0xc3, 0x7e, 0x8f, 0xcb, 0xdd, 0x9a, 0x49, 0xe8, 0x23, 0x74, 0xd5, 0x24, 0x44, 0x42, + 0x9b, 0x6e, 0x9a, 0x0d, 0xf2, 0xaf, 0x47, 0xe9, 0xd4, 0x58, 0x1d, 0xbe, 0xc7, 0xc6, + 0x0f, 0xb9, 0x33, 0x79, 0x4e, 0xc6, 0x88, 0x16, 0xbe, 0xd4, 0x2e, 0x97, 0xfb, 0xbc, + 0x91, 0xbd, 0x5e, 0x25, 0x69, 0x07, 0xb3, 0x9d, 0x24, 0xad, 0x54, 0xb5, 0x06, 0x4a, + 0x46, 0xb4, 0x01, 0x83, 0x38, 0x26, 0xfe, 0x4d, 0xff, 0x2e, 0x9f, 0xcc, 0xca, 0x8c, + 0x54, 0xf7, 0x83, 0x25, 0x4d, 0x28, 0x05, 0xe9, 0x56, 0x04, 0x41, 0x72, 0xa7, 0x65, + 0x81, 0xff, 0xfd, 0x45, 0x8b, 0x6a, 0x64, 0x69, 0xdc, 0x40, 0xf9, 0x4e, 0x60, 0x65, + 0xf9, 0x9c, 0x3f, 0x63, 0xda, 0x89, 0xf3, 0x26, 0x0a, 0xfe, 0xde, 0x0f, 0xfa, 0x0c, + 0xd3, 0x3a, 0xb0, 0x89, 0xb1, 0x31, 0xed, 0x55, 0x40, 0x29, 0x06, 0xba, 0xf8, 0x0b, + 0xcc, 0x64, 0x3d, 0xf9, 0x34, 0x1c, 0xce, 0x9a, 0x55, 0x3b, 0x5a, 0xe5, 0x11, 0xe5, + 0xdc, 0xd2, 0x83, 0x5c, 0x3b, 0xf5, 0x71, 0xe8, 0xaa, 0xd1, 0x61, 0x8c, 0xf7, 0x06, + 0xd9, 0x14, 0xe6, 0xa3, 0x99, 0xd1, 0x8d, 0xeb, 0xf5, 0x6b, 0x3b, 0x46, 0xc5, 0xd4, + 0x56, 0x2f, 0x1c, 0x7d, 0x24, 0x2d, 0xdc, 0x53, 0xa5, 0x73, 0x63, 0x6e, 0x75, 0x3c, + 0x91, 0x52, 0x4c, 0xb9, 0x3f, 0xcd, 0x88, 0xa2, 0x3b, 0xe9, 0xb3, 0x4e, 0xca, 0xb4, + 0xbf, 0x89, 0x71, 0x01, 0x34, 0xfc, 0xe8, 0x34, 0x5b, 0xcd, 0x6a, 0x5a, 0x3d, 0x72, + 0x1e, 0xa8, 0xb6, 0x20, 0x7c, 0x2f, 0xcf, 0x81, 0x75, 0x80, 0xe0, 0xa6, 0x3d, 0xb4, + 0x37, 0x7c, 0x86, 0xe4, 0x15, 0x1e, 0xd8, 0xd3, 0x0a, 0x71, + ], + ock: [ + 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, + 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, + 0x01, 0xd9, 0xfb, 0xa3, + ], + op: [ + 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, + 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, + 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, + 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, + 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, + ], + c_out: [ + 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, + 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, + 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, + 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, + 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, + 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x73, 0xa2, 0x5e, 0xba, 0x9b, 0xd7, 0xa8, 0xed, 0x2b, 0x5b, 0x1b, 0x8d, 0x5a, 0x05, + 0x6b, 0xde, 0x8d, 0x05, 0xe6, 0xa2, 0x80, 0x67, 0xb3, 0x84, 0x57, 0x91, 0xbe, 0xbf, + 0xa7, 0xae, 0x2a, 0xcd, 0x36, 0x32, 0x6f, 0xe6, 0x27, 0xbe, 0xe8, 0x0e, 0x32, 0x92, + 0xe0, 0xe5, 0x13, 0x2d, 0xe1, 0x6c, 0xa4, 0xf8, 0x1e, 0x5a, 0x6f, 0xc0, 0x9c, 0x95, + 0xff, 0x13, 0xb5, 0x2e, 0x96, 0xb7, 0x89, 0x0f, + ], + ovk: [ + 0xf5, 0xe8, 0xde, 0xd8, 0x18, 0x92, 0x51, 0x1c, 0xc2, 0x85, 0x1b, 0x00, 0xb8, 0x32, + 0x71, 0x2a, 0x6d, 0x3b, 0xa5, 0x66, 0x65, 0x17, 0xbc, 0xd3, 0x56, 0x76, 0x21, 0xa7, + 0xcf, 0x84, 0x45, 0x58, + ], + default_d: [ + 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, + ], + default_pk_d: [ + 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, + 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, + 0x01, 0x70, 0x89, 0x1a, + ], + v: 17209482587585417762, + rseed: [ + 0xfc, 0x54, 0x88, 0x62, 0xf5, 0xa0, 0x70, 0x94, 0xfd, 0x42, 0x8a, 0x7b, 0xbc, 0x15, + 0xd7, 0xb3, 0x8d, 0x05, 0x36, 0x2c, 0x9c, 0xa9, 0x85, 0xf5, 0x8a, 0x76, 0x64, 0x7d, + 0x2b, 0xe4, 0xc2, 0xcd, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x6b, 0x3d, 0x17, 0xd6, 0x87, 0x09, 0x71, 0xd7, 0xa0, 0x98, 0xba, 0xf7, 0x2c, + 0x6f, 0x6f, 0x12, 0x14, 0xcf, 0x1f, 0xaa, 0xe4, 0x88, 0xbd, 0x7d, 0xe2, 0x59, 0xd3, + 0x41, 0x5c, 0x2f, 0x0d, 0xde, 0xc7, 0x45, 0x70, 0x04, 0xf3, 0x57, 0x08, 0xd1, 0xec, + 0xcc, 0xcc, 0x0d, 0xf6, 0x5a, 0x04, 0x94, 0x3a, 0xd5, 0xcb, 0xc1, 0x3f, 0x29, 0x5f, + 0x00, 0x0f, 0xe0, 0x56, 0xc4, 0x0b, 0x2d, 0x88, 0xf2, 0x7d, 0xc3, 0x4c, 0xfe, 0xb8, + 0x03, 0xbe, 0x34, 0x83, 0xa9, 0xeb, 0xf9, 0xb5, 0xa9, 0x02, 0x60, 0x57, 0x72, 0x5d, + 0x63, 0xea, 0xd2, 0xc0, 0xc0, 0xff, 0x1f, 0xe2, 0x6a, 0xc1, 0xe7, 0xbd, 0xfc, 0xd6, + 0xfa, 0xd8, 0x75, 0x84, 0x2d, 0x19, 0x4f, 0x33, 0x17, 0x50, 0x46, 0x2c, 0x06, 0xb8, + 0xd7, 0x98, 0x2d, 0x67, 0x99, 0x5e, 0xd5, 0xd3, 0xae, 0x96, 0xa0, 0x5a, 0xe0, 0x06, + 0x7f, 0x4e, 0xb1, 0xc7, 0xc9, 0x32, 0x31, 0xbd, 0x39, 0x77, 0x3c, 0xbe, 0x0a, 0x9d, + 0x66, 0xb0, 0xc9, 0xaa, 0x8c, 0xff, 0x6a, 0x37, 0x6e, 0x1f, 0x37, 0x2e, 0xac, 0x6a, + 0xc4, 0xe4, 0x6c, 0xc0, 0x94, 0x22, 0x45, 0xd4, 0xc2, 0xdc, 0xf0, 0x2d, 0x76, 0x40, + 0xff, 0xcc, 0x5a, 0x6a, 0xc3, 0xa8, 0x7f, 0x5c, 0x41, 0x15, 0x51, 0xbc, 0xc2, 0xf2, + 0x6c, 0xb9, 0x49, 0x61, 0xd5, 0x3f, 0x95, 0xdd, 0xb1, 0x9a, 0xe9, 0x30, 0xc8, 0xd7, + 0x0f, 0x03, 0x1b, 0x29, 0xa5, 0xdf, 0x99, 0xff, 0x36, 0x69, 0x5e, 0x80, 0x2c, 0xbc, + 0xb6, 0xb5, 0x8c, 0x1b, 0xa7, 0xed, 0x5e, 0xac, 0xfa, 0x76, 0x41, 0x4a, 0x41, 0xad, + 0x4a, 0x44, 0xf7, 0x1f, 0x1b, 0x58, 0x0d, 0x34, 0xc3, 0xa9, 0x52, 0x92, 0x0b, 0x25, + 0x4a, 0x14, 0x5f, 0xea, 0x51, 0x7f, 0x5b, 0x42, 0xb2, 0xf6, 0x5e, 0xcd, 0x0f, 0x82, + 0x59, 0x54, 0x78, 0xd8, 0x0a, 0xe5, 0xc8, 0xce, 0xea, 0x12, 0xa1, 0x61, 0xcc, 0xbb, + 0x5e, 0xac, 0x09, 0x99, 0x0f, 0xc6, 0x19, 0xa4, 0x60, 0x80, 0x43, 0x6d, 0xbd, 0x08, + 0xd7, 0x47, 0x84, 0xaf, 0x00, 0x2d, 0x58, 0xe0, 0x6f, 0xaf, 0x7f, 0x3c, 0xea, 0xe7, + 0xd3, 0x41, 0x9b, 0x1f, 0xca, 0x26, 0x5a, 0x55, 0x59, 0xcf, 0x9e, 0x2d, 0x3b, 0x60, + 0x97, 0x8d, 0x81, 0xa6, 0x78, 0xb9, 0xed, 0x8e, 0x44, 0x86, 0xb4, 0xd1, 0x46, 0x09, + 0xd6, 0xc1, 0x27, 0xc0, 0xc2, 0xfb, 0xff, 0xe3, 0x0a, 0x60, 0xf7, 0xbf, 0xf1, 0xd9, + 0xfb, 0x83, 0x00, 0xed, 0x00, 0x92, 0x53, 0xba, 0x9b, 0x99, 0x6f, 0xa0, 0x52, 0x41, + 0xb1, 0x0f, 0x5a, 0xc9, 0xa8, 0x40, 0x8e, 0x92, 0x5b, 0x62, 0x6b, 0xb2, 0x1a, 0x47, + 0x1f, 0xe3, 0xbe, 0xde, 0x52, 0xbb, 0xa0, 0x97, 0xb2, 0xa9, 0x9a, 0x9b, 0xa5, 0xa8, + 0x66, 0x58, 0xc3, 0xfd, 0x9e, 0xc5, 0x5b, 0xfa, 0x9b, 0x32, 0x85, 0x67, 0x25, 0x4a, + 0xb3, 0x6d, 0x2c, 0x7f, 0x44, 0xd2, 0xc7, 0xe1, 0x3e, 0xb5, 0x4b, 0xeb, 0x70, 0xea, + 0x8f, 0xa9, 0x4b, 0x6c, 0x6e, 0x01, 0x2d, 0x79, 0xe3, 0xf5, 0x36, 0x89, 0xc2, 0xb1, + 0xa1, 0x8e, 0xaf, 0x2d, 0x47, 0x1d, 0x13, 0xc1, 0xab, 0x39, 0xd9, 0x19, 0x4a, 0xe8, + 0x43, 0xab, 0x1d, 0x28, 0xff, 0xa8, 0xf6, 0x9d, 0xc7, 0xe1, 0x5c, 0xc3, 0x8b, 0x12, + 0xe8, 0xfc, 0xd7, 0x92, 0x55, 0xb7, 0x21, 0x60, 0x56, 0xd9, 0xed, 0xb7, 0x48, 0x2f, + 0xb9, 0x8a, 0xa0, 0x33, 0xb6, 0x5e, 0x51, 0xc1, 0xa0, 0x8b, 0x8a, 0x11, 0xd8, 0x4d, + 0x04, 0x09, 0xb7, 0x34, 0xf4, 0x52, 0xaa, 0xf0, 0xd6, 0xb1, 0x8f, 0x50, 0x25, 0x86, + 0x83, 0xd3, 0xf9, 0xa7, 0x6d, 0x39, 0x9f, 0xd0, 0x47, 0xee, 0xe2, 0x88, 0xbb, 0x45, + 0x85, 0x85, 0x1d, 0xc9, 0x3e, 0xcc, 0xc6, 0x23, + ], + cv_net: [ + 0xe8, 0x06, 0x5c, 0x40, 0x96, 0xd3, 0x54, 0x33, 0x40, 0x01, 0x1f, 0x58, 0x90, 0xb1, + 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, + 0x87, 0xe5, 0x05, 0xad, + ], + nf_old: [ + 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, + 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, + 0x45, 0x89, 0x35, 0x14, + ], + cmx: [ + 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, + 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, + 0xc7, 0x4d, 0x19, 0x1b, + ], + esk: [ + 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, + 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, + 0x99, 0xbd, 0x4c, 0x13, + ], + ephemeral_key: [ + 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, + 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, + 0x0e, 0x12, 0xbc, 0x1e, + ], + shared_secret: [ + 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, + 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, + 0x5c, 0xb8, 0xf3, 0x31, + ], + k_enc: [ + 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, + 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, + 0xf2, 0x2f, 0x9f, 0xf8, + ], + p_enc: [ + 0x03, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, + 0x4c, 0xd1, 0x3b, 0x5d, 0xd4, 0xee, 0xfc, 0x54, 0x88, 0x62, 0xf5, 0xa0, 0x70, 0x94, + 0xfd, 0x42, 0x8a, 0x7b, 0xbc, 0x15, 0xd7, 0xb3, 0x8d, 0x05, 0x36, 0x2c, 0x9c, 0xa9, + 0x85, 0xf5, 0x8a, 0x76, 0x64, 0x7d, 0x2b, 0xe4, 0xc2, 0xcd, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x6b, 0x3d, 0x17, 0xd6, 0x87, 0x09, 0x71, 0xd7, 0xa0, 0x98, 0xba, 0xf7, 0x2c, + 0x6f, 0x6f, 0x12, 0x14, 0xcf, 0x1f, 0xaa, 0xe4, 0x88, 0xbd, 0x7d, 0xe2, 0x59, 0xd3, + 0x41, 0x5c, 0x2f, 0x0d, 0xde, 0xc7, 0x45, 0x70, 0x04, 0xf3, 0x57, 0x08, 0xd1, 0xec, + 0xcc, 0xcc, 0x0d, 0xf6, 0x5a, 0x04, 0x94, 0x3a, 0xd5, 0xcb, 0xc1, 0x3f, 0x29, 0x5f, + 0x00, 0x0f, 0xe0, 0x56, 0xc4, 0x0b, 0x2d, 0x88, 0xf2, 0x7d, 0xc3, 0x4c, 0xfe, 0xb8, + 0x03, 0xbe, 0x34, 0x83, 0xa9, 0xeb, 0xf9, 0xb5, 0xa9, 0x02, 0x60, 0x57, 0x72, 0x5d, + 0x63, 0xea, 0xd2, 0xc0, 0xc0, 0xff, 0x1f, 0xe2, 0x6a, 0xc1, 0xe7, 0xbd, 0xfc, 0xd6, + 0xfa, 0xd8, 0x75, 0x84, 0x2d, 0x19, 0x4f, 0x33, 0x17, 0x50, 0x46, 0x2c, 0x06, 0xb8, + 0xd7, 0x98, 0x2d, 0x67, 0x99, 0x5e, 0xd5, 0xd3, 0xae, 0x96, 0xa0, 0x5a, 0xe0, 0x06, + 0x7f, 0x4e, 0xb1, 0xc7, 0xc9, 0x32, 0x31, 0xbd, 0x39, 0x77, 0x3c, 0xbe, 0x0a, 0x9d, + 0x66, 0xb0, 0xc9, 0xaa, 0x8c, 0xff, 0x6a, 0x37, 0x6e, 0x1f, 0x37, 0x2e, 0xac, 0x6a, + 0xc4, 0xe4, 0x6c, 0xc0, 0x94, 0x22, 0x45, 0xd4, 0xc2, 0xdc, 0xf0, 0x2d, 0x76, 0x40, + 0xff, 0xcc, 0x5a, 0x6a, 0xc3, 0xa8, 0x7f, 0x5c, 0x41, 0x15, 0x51, 0xbc, 0xc2, 0xf2, + 0x6c, 0xb9, 0x49, 0x61, 0xd5, 0x3f, 0x95, 0xdd, 0xb1, 0x9a, 0xe9, 0x30, 0xc8, 0xd7, + 0x0f, 0x03, 0x1b, 0x29, 0xa5, 0xdf, 0x99, 0xff, 0x36, 0x69, 0x5e, 0x80, 0x2c, 0xbc, + 0xb6, 0xb5, 0x8c, 0x1b, 0xa7, 0xed, 0x5e, 0xac, 0xfa, 0x76, 0x41, 0x4a, 0x41, 0xad, + 0x4a, 0x44, 0xf7, 0x1f, 0x1b, 0x58, 0x0d, 0x34, 0xc3, 0xa9, 0x52, 0x92, 0x0b, 0x25, + 0x4a, 0x14, 0x5f, 0xea, 0x51, 0x7f, 0x5b, 0x42, 0xb2, 0xf6, 0x5e, 0xcd, 0x0f, 0x82, + 0x59, 0x54, 0x78, 0xd8, 0x0a, 0xe5, 0xc8, 0xce, 0xea, 0x12, 0xa1, 0x61, 0xcc, 0xbb, + 0x5e, 0xac, 0x09, 0x99, 0x0f, 0xc6, 0x19, 0xa4, 0x60, 0x80, 0x43, 0x6d, 0xbd, 0x08, + 0xd7, 0x47, 0x84, 0xaf, 0x00, 0x2d, 0x58, 0xe0, 0x6f, 0xaf, 0x7f, 0x3c, 0xea, 0xe7, + 0xd3, 0x41, 0x9b, 0x1f, 0xca, 0x26, 0x5a, 0x55, 0x59, 0xcf, 0x9e, 0x2d, 0x3b, 0x60, + 0x97, 0x8d, 0x81, 0xa6, 0x78, 0xb9, 0xed, 0x8e, 0x44, 0x86, 0xb4, 0xd1, 0x46, 0x09, + 0xd6, 0xc1, 0x27, 0xc0, 0xc2, 0xfb, 0xff, 0xe3, 0x0a, 0x60, 0xf7, 0xbf, 0xf1, 0xd9, + 0xfb, 0x83, 0x00, 0xed, 0x00, 0x92, 0x53, 0xba, 0x9b, 0x99, 0x6f, 0xa0, 0x52, 0x41, + 0xb1, 0x0f, 0x5a, 0xc9, 0xa8, 0x40, 0x8e, 0x92, 0x5b, 0x62, 0x6b, 0xb2, 0x1a, 0x47, + 0x1f, 0xe3, 0xbe, 0xde, 0x52, 0xbb, 0xa0, 0x97, 0xb2, 0xa9, 0x9a, 0x9b, 0xa5, 0xa8, + 0x66, 0x58, 0xc3, 0xfd, 0x9e, 0xc5, 0x5b, 0xfa, 0x9b, 0x32, 0x85, 0x67, 0x25, 0x4a, + 0xb3, 0x6d, 0x2c, 0x7f, 0x44, 0xd2, 0xc7, 0xe1, 0x3e, 0xb5, 0x4b, 0xeb, 0x70, 0xea, + 0x8f, 0xa9, 0x4b, 0x6c, 0x6e, 0x01, 0x2d, 0x79, 0xe3, 0xf5, 0x36, 0x89, 0xc2, 0xb1, + 0xa1, 0x8e, 0xaf, 0x2d, 0x47, 0x1d, 0x13, 0xc1, 0xab, 0x39, 0xd9, 0x19, 0x4a, 0xe8, + 0x43, 0xab, 0x1d, 0x28, 0xff, 0xa8, 0xf6, 0x9d, 0xc7, 0xe1, 0x5c, 0xc3, 0x8b, 0x12, + 0xe8, 0xfc, 0xd7, 0x92, 0x55, 0xb7, 0x21, 0x60, 0x56, 0xd9, 0xed, 0xb7, 0x48, 0x2f, + 0xb9, 0x8a, 0xa0, 0x33, 0xb6, 0x5e, 0x51, 0xc1, 0xa0, 0x8b, 0x8a, 0x11, 0xd8, 0x4d, + 0x04, 0x09, 0xb7, 0x34, 0xf4, 0x52, 0xaa, 0xf0, 0xd6, 0xb1, 0x8f, 0x50, 0x25, 0x86, + 0x83, 0xd3, 0xf9, 0xa7, 0x6d, 0x39, 0x9f, 0xd0, 0x47, 0xee, 0xe2, 0x88, 0xbb, 0x45, + 0x85, 0x85, 0x1d, 0xc9, 0x3e, 0xcc, 0xc6, 0x23, + ], + c_enc: [ + 0x73, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, + 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, + 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, + 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0xad, 0xc7, 0x88, 0x7c, + 0x34, 0x4d, 0x78, 0x79, 0x73, 0x3d, 0x26, 0x30, 0xbd, 0x45, 0x07, 0x25, 0xcd, 0xfc, + 0xef, 0x8f, 0xe4, 0x0f, 0xf0, 0xdc, 0x6f, 0x45, 0x9e, 0xc6, 0x67, 0x38, 0x5a, 0x94, + 0xfb, 0x63, 0x44, 0x5a, 0x61, 0xc7, 0x3d, 0x9d, 0x16, 0x1b, 0x77, 0x06, 0xf6, 0xb3, + 0x26, 0xf4, 0x07, 0xc2, 0xde, 0x59, 0xe3, 0xe6, 0x01, 0xdb, 0xa0, 0x00, 0xe7, 0x73, + 0x81, 0x5d, 0xb0, 0x97, 0x22, 0xe9, 0xbd, 0x23, 0x07, 0x4d, 0x20, 0x6d, 0xbe, 0xfd, + 0x0b, 0x7f, 0x8b, 0x55, 0x14, 0xee, 0x62, 0x46, 0xb5, 0xde, 0x97, 0x68, 0xad, 0x50, + 0x18, 0x17, 0xa4, 0x42, 0x04, 0x87, 0x07, 0x78, 0x61, 0xa0, 0x6c, 0xf5, 0xfa, 0xa0, + 0xae, 0x0d, 0xf9, 0x03, 0x02, 0x51, 0xa9, 0xe3, 0x9e, 0x7c, 0xde, 0x48, 0x3e, 0xd8, + 0x28, 0xd8, 0xb2, 0x7e, 0xbd, 0x6d, 0xa9, 0xca, 0x96, 0x54, 0xaf, 0xc1, 0xdf, 0x94, + 0x00, 0xb2, 0xbe, 0xc7, 0x60, 0xfb, 0x26, 0x00, 0xa4, 0x53, 0x67, 0x3f, 0x6e, 0x7c, + 0x89, 0x4b, 0x9c, 0xcd, 0x8a, 0x57, 0x2d, 0x24, 0xa5, 0x47, 0x31, 0x22, 0xfe, 0x40, + 0x06, 0xe8, 0x0c, 0x9a, 0x97, 0x5e, 0x93, 0xbe, 0xc5, 0x7e, 0xbc, 0x4c, 0x44, 0xb2, + 0x8e, 0xb0, 0x1f, 0xbc, 0xb2, 0xb2, 0xde, 0x55, 0x9b, 0xf0, 0x2d, 0x7b, 0x2c, 0xe4, + 0xf3, 0xd1, 0x1e, 0x86, 0xcb, 0xaa, 0x10, 0x00, 0xee, 0xbd, 0x0d, 0x1b, 0x58, 0x8c, + 0x99, 0xd7, 0xf9, 0xd9, 0x57, 0xc6, 0x4e, 0x0a, 0x1e, 0x59, 0x67, 0x66, 0xe7, 0x6c, + 0x0e, 0xdc, 0xc6, 0xd9, 0xef, 0x34, 0x58, 0x74, 0x52, 0x04, 0x46, 0x39, 0x48, 0xd9, + 0x78, 0xd1, 0x3c, 0x4b, 0xc0, 0xf4, 0x2c, 0xc9, 0xb8, 0x93, 0x65, 0x27, 0x71, 0xf6, + 0xd1, 0x17, 0x7c, 0x78, 0x58, 0xf5, 0x77, 0x03, 0xec, 0x38, 0x3c, 0x3b, 0xad, 0x82, + 0x1b, 0x2f, 0x82, 0x87, 0x9c, 0x3e, 0x1d, 0x39, 0x91, 0xd2, 0x09, 0xb5, 0xc8, 0x94, + 0xc4, 0x65, 0xdd, 0x5e, 0xd9, 0x57, 0x19, 0x27, 0x2f, 0x9f, 0x03, 0x4c, 0xd9, 0x41, + 0xa0, 0x32, 0x33, 0xe1, 0x10, 0xd5, 0x80, 0xc1, 0x93, 0xc1, 0x9a, 0x92, 0x91, 0x19, + 0x45, 0x5a, 0xa6, 0x2e, 0x10, 0x35, 0x78, 0xa2, 0xd6, 0x46, 0x06, 0x26, 0xba, 0x04, + 0x37, 0x82, 0xb8, 0xd1, 0x3a, 0x31, 0x4e, 0x51, 0xf4, 0xa2, 0x81, 0x59, 0x32, 0x5f, + 0xbb, 0x35, 0xbe, 0xbb, 0xba, 0xf5, 0x27, 0x25, 0x64, 0xa7, 0xf5, 0x3f, 0x4c, 0x38, + 0xb0, 0xf6, 0xea, 0xed, 0x1a, 0xfc, 0x71, 0x31, 0x59, 0x87, 0xac, 0xbc, 0x95, 0x91, + 0x82, 0xab, 0xd3, 0xee, 0x9d, 0x87, 0x18, 0xc2, 0x26, 0x2f, 0x53, 0x1b, 0xfb, 0x57, + 0x1b, 0xb7, 0x4e, 0x9a, 0xf3, 0x63, 0x61, 0x36, 0x75, 0xce, 0xed, 0x6f, 0x97, 0xbe, + 0x67, 0x4c, 0x43, 0xf2, 0xad, 0x13, 0xdf, 0x86, 0x8d, 0xf6, 0xd4, 0x6f, 0x80, 0x72, + 0x6b, 0xe7, 0x88, 0x79, 0x04, 0xdf, 0x5b, 0x6b, 0xb5, 0x15, 0x7a, 0x87, 0x42, 0x06, + 0xe1, 0x77, 0x8a, 0x5d, 0x08, 0x4f, 0xd7, 0x60, 0x98, 0x6d, 0xb8, 0x39, 0xb0, 0xd9, + 0x6c, 0xcd, 0x41, 0x34, 0x38, 0xef, 0x02, 0xc7, 0x9e, 0xba, 0xc9, 0xe7, 0x49, 0xf8, + 0x93, 0x60, 0xb7, 0x5d, 0xcd, 0x1e, 0xb7, 0x73, 0x94, 0x73, 0xe3, 0x1f, 0xa9, 0xca, + 0xe4, 0x94, 0x30, 0x6e, 0xa4, 0x82, 0x4a, 0xb4, 0xa9, 0xbf, 0x92, 0x5d, 0xb7, 0x4c, + 0xf3, 0xdb, 0xac, 0x38, 0x93, 0xe7, 0xf0, 0x71, 0x00, 0x77, 0xff, 0x37, 0x90, 0x2d, + 0x18, 0x7f, 0xce, 0xbe, 0xf9, 0x76, 0xd6, 0x2c, 0xae, 0xfd, 0xcc, 0x14, 0x8c, 0x68, + 0xd7, 0x7e, 0x3e, 0xb2, 0x1d, 0xd5, 0x0c, 0x34, 0x01, 0x08, 0x34, 0x23, 0xf0, 0x38, + 0x11, 0x73, 0x0b, 0xc5, 0xf8, 0x14, 0xe0, 0x99, 0x02, 0xf0, 0x60, 0x80, 0xbf, 0xb4, + 0x8b, 0x34, 0x1e, 0xce, 0x80, 0xac, 0x29, 0xcb, 0x41, 0xe3, 0x20, 0x9d, 0x07, 0x9a, + 0xc8, 0x4e, 0x85, 0x1b, 0xfb, 0x26, 0xdd, 0x39, 0xd9, 0x66, 0x2a, 0x11, 0x90, 0x28, + 0x17, 0xb0, 0x8d, 0xa3, 0x89, 0x7a, 0x5c, 0x87, 0x62, 0x22, + ], + ock: [ + 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, + 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, + 0x04, 0xa7, 0x8c, 0x0b, + ], + op: [ + 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, + 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, + 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, + 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, + 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, + ], + c_out: [ + 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, + 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, + 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, + 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, + 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, + 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xa4, 0xd7, 0x9c, 0x81, 0x9a, 0x6c, 0x5e, 0x01, 0x67, 0xfc, 0xa9, 0x8c, 0xe2, 0x62, + 0x98, 0x15, 0xf9, 0xba, 0xc9, 0x26, 0xb6, 0x27, 0x18, 0xcf, 0xbe, 0x50, 0x45, 0xd9, + 0x2d, 0xd7, 0x1c, 0xd3, 0x36, 0x75, 0xd5, 0x56, 0xe0, 0x77, 0x1e, 0x40, 0xcc, 0x3d, + 0x61, 0x8d, 0x9b, 0xda, 0x13, 0x2f, 0x13, 0x95, 0x3d, 0x82, 0x43, 0x2e, 0x81, 0x59, + 0x4a, 0x97, 0x1e, 0x98, 0xb0, 0x71, 0x40, 0x39, + ], + ovk: [ + 0x67, 0x79, 0x9a, 0x90, 0x01, 0xa2, 0xed, 0x36, 0x76, 0xa8, 0xb4, 0x03, 0xae, 0x25, + 0xff, 0xd7, 0x72, 0xf7, 0x08, 0x1e, 0x9a, 0x32, 0xbc, 0xc1, 0xc5, 0xe2, 0xed, 0xd4, + 0xe2, 0xa6, 0x57, 0x6b, + ], + default_d: [ + 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, + ], + default_pk_d: [ + 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, + 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, + 0x44, 0x6d, 0xf4, 0x39, + ], + v: 7122345086698755501, + rseed: [ + 0x2d, 0xd4, 0x17, 0xdf, 0x26, 0xdc, 0xd2, 0x20, 0xf2, 0xb7, 0x31, 0x77, 0x2b, 0x43, + 0x9e, 0x96, 0xd6, 0x14, 0xe1, 0xfa, 0xcb, 0x48, 0x6c, 0x7a, 0x7d, 0x51, 0x71, 0xb1, + 0xde, 0x35, 0x9f, 0x6a, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0xd3, 0xa9, 0x6f, 0x64, 0x9c, 0x96, 0x91, 0x02, 0xa1, 0x96, 0x4f, 0xb4, 0xb4, + 0xa1, 0xa4, 0x27, 0x9c, 0x68, 0xe6, 0xc3, 0x72, 0xe4, 0x21, 0x87, 0xd7, 0x54, 0xe8, + 0x04, 0xa6, 0x16, 0x53, 0x09, 0x20, 0x69, 0xfb, 0x9b, 0x6d, 0x25, 0x26, 0x68, 0x90, + 0x80, 0x8b, 0x01, 0x5d, 0xf2, 0x8c, 0x80, 0x10, 0x65, 0xda, 0x6f, 0xeb, 0xdc, 0x1a, + 0x56, 0xbf, 0xd0, 0x02, 0x62, 0x5a, 0xcf, 0xaa, 0x53, 0x73, 0xfd, 0xe1, 0x49, 0xc1, + 0xcf, 0xc3, 0x64, 0x9b, 0x48, 0x69, 0x69, 0x6d, 0x44, 0xec, 0xb1, 0x24, 0x79, 0xc5, + 0xeb, 0xef, 0x99, 0x5f, 0x10, 0x02, 0x9f, 0x8b, 0x53, 0x0e, 0xeb, 0x3f, 0xdc, 0x2e, + 0x50, 0xe8, 0x75, 0x7f, 0xc0, 0xbb, 0x9e, 0x26, 0x30, 0x23, 0xdb, 0x82, 0xf8, 0x78, + 0xd9, 0xac, 0x7f, 0xfb, 0x0b, 0xd4, 0x39, 0x1d, 0xf1, 0xd8, 0x79, 0x89, 0x9a, 0x3e, + 0xf5, 0x7b, 0xfd, 0x0d, 0x1f, 0x77, 0x55, 0x64, 0x8e, 0xdd, 0x85, 0xbb, 0x05, 0x2a, + 0x6e, 0xdf, 0x71, 0xcd, 0x26, 0x28, 0xc9, 0x87, 0x42, 0x9f, 0x36, 0xdc, 0x50, 0x5c, + 0xcc, 0x43, 0xf3, 0x0e, 0x7a, 0x86, 0x9c, 0x9e, 0x25, 0x5e, 0x2a, 0xf9, 0xfc, 0xf3, + 0x0c, 0x12, 0x17, 0x96, 0xd1, 0x90, 0x00, 0x09, 0x60, 0xcb, 0x6f, 0xe2, 0xf1, 0xbf, + 0x24, 0x61, 0x18, 0xb4, 0x98, 0xf3, 0x24, 0x7f, 0x9d, 0x48, 0x4c, 0x73, 0xcf, 0x09, + 0x39, 0x30, 0x39, 0xe4, 0x53, 0x26, 0xb8, 0xff, 0xff, 0xb3, 0xe7, 0xe6, 0x15, 0x9c, + 0x46, 0x69, 0x9f, 0x10, 0x07, 0x92, 0xd4, 0x67, 0x29, 0x50, 0x34, 0x8a, 0x90, 0x55, + 0x2e, 0x45, 0x94, 0x3b, 0xee, 0xac, 0xf0, 0x3f, 0x32, 0x16, 0xf9, 0x4e, 0x27, 0x4d, + 0x63, 0xd6, 0x37, 0xd9, 0xf1, 0x90, 0xe8, 0xa2, 0x66, 0xcd, 0xee, 0xf1, 0x53, 0x53, + 0x0b, 0xee, 0x5c, 0xb8, 0x35, 0x52, 0x60, 0x50, 0x5c, 0x2c, 0x2e, 0x5d, 0x99, 0x0f, + 0xff, 0xdc, 0x34, 0xec, 0x0f, 0xf7, 0xf1, 0xaf, 0x81, 0xb2, 0x4c, 0xed, 0x0e, 0xfa, + 0x62, 0x13, 0xda, 0x6c, 0x7c, 0x60, 0xc4, 0x87, 0xf5, 0xf7, 0xb0, 0x3f, 0x81, 0x60, + 0xa0, 0x57, 0xf4, 0x6d, 0x05, 0xbf, 0x82, 0x18, 0xb3, 0xad, 0xd9, 0xc0, 0x68, 0x93, + 0xbd, 0x02, 0xdb, 0x9b, 0x61, 0x19, 0x1d, 0xfb, 0x13, 0x3b, 0xfa, 0xbe, 0x48, 0x58, + 0xe4, 0x7a, 0x4c, 0xc3, 0x2e, 0x41, 0x6e, 0xc0, 0x8b, 0x8a, 0xc7, 0x91, 0x5a, 0x43, + 0x73, 0x3f, 0x44, 0x06, 0xe9, 0xd9, 0x67, 0xc5, 0x60, 0xf3, 0x44, 0xd7, 0xe9, 0x04, + 0xa2, 0x80, 0x45, 0xd9, 0x9f, 0x3a, 0xf8, 0xc8, 0x2e, 0x97, 0xe1, 0xb9, 0xc1, 0xb2, + 0x05, 0xe5, 0x85, 0xfb, 0xeb, 0xb4, 0x8f, 0xaf, 0x58, 0xf1, 0xb6, 0x5d, 0xca, 0x24, + 0x97, 0xe0, 0x9a, 0x70, 0xaa, 0xd4, 0x86, 0x5f, 0x85, 0x71, 0x5a, 0x28, 0x0e, 0x18, + 0x6f, 0x3f, 0xc1, 0x74, 0x0d, 0x81, 0x84, 0xd3, 0x3e, 0x83, 0x22, 0x16, 0x95, 0x21, + 0xcd, 0xc1, 0x32, 0x21, 0x29, 0x39, 0xc8, 0x4a, 0x10, 0x89, 0x64, 0xe2, 0xde, 0x74, + 0xb6, 0xea, 0x55, 0xb4, 0xcb, 0x8f, 0x6f, 0x9b, 0xee, 0x98, 0xb1, 0x0d, 0x41, 0x51, + 0x09, 0x45, 0x5f, 0x48, 0xb7, 0x76, 0x08, 0x2d, 0xc3, 0x0b, 0x4b, 0xc7, 0x34, 0x77, + 0x07, 0x55, 0x11, 0x70, 0x03, 0x08, 0x15, 0x8c, 0xe2, 0xf2, 0xf9, 0xbf, 0x0f, 0x69, + 0x1b, 0x2c, 0xe5, 0x3e, 0x61, 0x14, 0x2c, 0xb7, 0x40, 0xc1, 0x5b, 0x7b, 0x62, 0x3c, + 0xf4, 0x8b, 0x3f, 0x7b, 0xfe, 0xfa, 0x31, 0xbc, 0xdc, 0x66, 0x5c, 0x6d, 0x71, 0x23, + 0xe9, 0x53, 0x50, 0x81, 0x13, 0x75, 0x94, 0x7b, 0x05, 0x5a, 0x43, 0xdb, 0x07, 0xe0, + 0x3f, 0x33, 0x62, 0x7d, 0xf5, 0xc6, 0x38, 0xbf, + ], + cv_net: [ + 0x00, 0x55, 0xf3, 0x5c, 0x6c, 0x82, 0x62, 0xac, 0x74, 0xfe, 0x27, 0xd7, 0x2a, 0x33, + 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, + 0x71, 0x55, 0x00, 0xb5, + ], + nf_old: [ + 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, + 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, + 0xa3, 0x18, 0x53, 0x3e, + ], + cmx: [ + 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, + 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, + 0x51, 0x5b, 0x97, 0x1c, + ], + esk: [ + 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, + 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, + 0x46, 0x1e, 0xec, 0x29, + ], + ephemeral_key: [ + 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, + 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, + 0x97, 0xf3, 0x23, 0x1c, + ], + shared_secret: [ + 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, + 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, + 0x2b, 0xa0, 0x63, 0x08, + ], + k_enc: [ + 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, + 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, + 0x2a, 0x20, 0x47, 0x0b, + ], + p_enc: [ + 0x03, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, + 0x6d, 0xdc, 0x1e, 0xa7, 0xd7, 0x62, 0x2d, 0xd4, 0x17, 0xdf, 0x26, 0xdc, 0xd2, 0x20, + 0xf2, 0xb7, 0x31, 0x77, 0x2b, 0x43, 0x9e, 0x96, 0xd6, 0x14, 0xe1, 0xfa, 0xcb, 0x48, + 0x6c, 0x7a, 0x7d, 0x51, 0x71, 0xb1, 0xde, 0x35, 0x9f, 0x6a, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0xd3, 0xa9, 0x6f, 0x64, 0x9c, 0x96, 0x91, 0x02, 0xa1, 0x96, 0x4f, 0xb4, 0xb4, + 0xa1, 0xa4, 0x27, 0x9c, 0x68, 0xe6, 0xc3, 0x72, 0xe4, 0x21, 0x87, 0xd7, 0x54, 0xe8, + 0x04, 0xa6, 0x16, 0x53, 0x09, 0x20, 0x69, 0xfb, 0x9b, 0x6d, 0x25, 0x26, 0x68, 0x90, + 0x80, 0x8b, 0x01, 0x5d, 0xf2, 0x8c, 0x80, 0x10, 0x65, 0xda, 0x6f, 0xeb, 0xdc, 0x1a, + 0x56, 0xbf, 0xd0, 0x02, 0x62, 0x5a, 0xcf, 0xaa, 0x53, 0x73, 0xfd, 0xe1, 0x49, 0xc1, + 0xcf, 0xc3, 0x64, 0x9b, 0x48, 0x69, 0x69, 0x6d, 0x44, 0xec, 0xb1, 0x24, 0x79, 0xc5, + 0xeb, 0xef, 0x99, 0x5f, 0x10, 0x02, 0x9f, 0x8b, 0x53, 0x0e, 0xeb, 0x3f, 0xdc, 0x2e, + 0x50, 0xe8, 0x75, 0x7f, 0xc0, 0xbb, 0x9e, 0x26, 0x30, 0x23, 0xdb, 0x82, 0xf8, 0x78, + 0xd9, 0xac, 0x7f, 0xfb, 0x0b, 0xd4, 0x39, 0x1d, 0xf1, 0xd8, 0x79, 0x89, 0x9a, 0x3e, + 0xf5, 0x7b, 0xfd, 0x0d, 0x1f, 0x77, 0x55, 0x64, 0x8e, 0xdd, 0x85, 0xbb, 0x05, 0x2a, + 0x6e, 0xdf, 0x71, 0xcd, 0x26, 0x28, 0xc9, 0x87, 0x42, 0x9f, 0x36, 0xdc, 0x50, 0x5c, + 0xcc, 0x43, 0xf3, 0x0e, 0x7a, 0x86, 0x9c, 0x9e, 0x25, 0x5e, 0x2a, 0xf9, 0xfc, 0xf3, + 0x0c, 0x12, 0x17, 0x96, 0xd1, 0x90, 0x00, 0x09, 0x60, 0xcb, 0x6f, 0xe2, 0xf1, 0xbf, + 0x24, 0x61, 0x18, 0xb4, 0x98, 0xf3, 0x24, 0x7f, 0x9d, 0x48, 0x4c, 0x73, 0xcf, 0x09, + 0x39, 0x30, 0x39, 0xe4, 0x53, 0x26, 0xb8, 0xff, 0xff, 0xb3, 0xe7, 0xe6, 0x15, 0x9c, + 0x46, 0x69, 0x9f, 0x10, 0x07, 0x92, 0xd4, 0x67, 0x29, 0x50, 0x34, 0x8a, 0x90, 0x55, + 0x2e, 0x45, 0x94, 0x3b, 0xee, 0xac, 0xf0, 0x3f, 0x32, 0x16, 0xf9, 0x4e, 0x27, 0x4d, + 0x63, 0xd6, 0x37, 0xd9, 0xf1, 0x90, 0xe8, 0xa2, 0x66, 0xcd, 0xee, 0xf1, 0x53, 0x53, + 0x0b, 0xee, 0x5c, 0xb8, 0x35, 0x52, 0x60, 0x50, 0x5c, 0x2c, 0x2e, 0x5d, 0x99, 0x0f, + 0xff, 0xdc, 0x34, 0xec, 0x0f, 0xf7, 0xf1, 0xaf, 0x81, 0xb2, 0x4c, 0xed, 0x0e, 0xfa, + 0x62, 0x13, 0xda, 0x6c, 0x7c, 0x60, 0xc4, 0x87, 0xf5, 0xf7, 0xb0, 0x3f, 0x81, 0x60, + 0xa0, 0x57, 0xf4, 0x6d, 0x05, 0xbf, 0x82, 0x18, 0xb3, 0xad, 0xd9, 0xc0, 0x68, 0x93, + 0xbd, 0x02, 0xdb, 0x9b, 0x61, 0x19, 0x1d, 0xfb, 0x13, 0x3b, 0xfa, 0xbe, 0x48, 0x58, + 0xe4, 0x7a, 0x4c, 0xc3, 0x2e, 0x41, 0x6e, 0xc0, 0x8b, 0x8a, 0xc7, 0x91, 0x5a, 0x43, + 0x73, 0x3f, 0x44, 0x06, 0xe9, 0xd9, 0x67, 0xc5, 0x60, 0xf3, 0x44, 0xd7, 0xe9, 0x04, + 0xa2, 0x80, 0x45, 0xd9, 0x9f, 0x3a, 0xf8, 0xc8, 0x2e, 0x97, 0xe1, 0xb9, 0xc1, 0xb2, + 0x05, 0xe5, 0x85, 0xfb, 0xeb, 0xb4, 0x8f, 0xaf, 0x58, 0xf1, 0xb6, 0x5d, 0xca, 0x24, + 0x97, 0xe0, 0x9a, 0x70, 0xaa, 0xd4, 0x86, 0x5f, 0x85, 0x71, 0x5a, 0x28, 0x0e, 0x18, + 0x6f, 0x3f, 0xc1, 0x74, 0x0d, 0x81, 0x84, 0xd3, 0x3e, 0x83, 0x22, 0x16, 0x95, 0x21, + 0xcd, 0xc1, 0x32, 0x21, 0x29, 0x39, 0xc8, 0x4a, 0x10, 0x89, 0x64, 0xe2, 0xde, 0x74, + 0xb6, 0xea, 0x55, 0xb4, 0xcb, 0x8f, 0x6f, 0x9b, 0xee, 0x98, 0xb1, 0x0d, 0x41, 0x51, + 0x09, 0x45, 0x5f, 0x48, 0xb7, 0x76, 0x08, 0x2d, 0xc3, 0x0b, 0x4b, 0xc7, 0x34, 0x77, + 0x07, 0x55, 0x11, 0x70, 0x03, 0x08, 0x15, 0x8c, 0xe2, 0xf2, 0xf9, 0xbf, 0x0f, 0x69, + 0x1b, 0x2c, 0xe5, 0x3e, 0x61, 0x14, 0x2c, 0xb7, 0x40, 0xc1, 0x5b, 0x7b, 0x62, 0x3c, + 0xf4, 0x8b, 0x3f, 0x7b, 0xfe, 0xfa, 0x31, 0xbc, 0xdc, 0x66, 0x5c, 0x6d, 0x71, 0x23, + 0xe9, 0x53, 0x50, 0x81, 0x13, 0x75, 0x94, 0x7b, 0x05, 0x5a, 0x43, 0xdb, 0x07, 0xe0, + 0x3f, 0x33, 0x62, 0x7d, 0xf5, 0xc6, 0x38, 0xbf, + ], + c_enc: [ + 0x7a, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, + 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, + 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, + 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0xd2, 0x1c, 0xf9, 0xbe, + 0xf6, 0xc6, 0xc5, 0x47, 0x62, 0xfa, 0x2a, 0x61, 0x45, 0x53, 0xcd, 0x9b, 0x45, 0x3e, + 0x23, 0xbe, 0x78, 0x88, 0x56, 0x69, 0x77, 0xf6, 0xc4, 0xe0, 0xe7, 0x7c, 0x90, 0xe6, + 0x1b, 0x01, 0x1a, 0xe9, 0x95, 0x5e, 0x62, 0x87, 0x04, 0xd6, 0x20, 0x36, 0x6e, 0xda, + 0xef, 0xcc, 0x17, 0x13, 0xc7, 0x48, 0xc5, 0xb3, 0x6a, 0x32, 0x76, 0x51, 0xaf, 0x94, + 0xcf, 0x94, 0x82, 0x10, 0xb6, 0x10, 0x8b, 0xe4, 0x82, 0x5b, 0xe5, 0x75, 0x2e, 0x7f, + 0xcd, 0xe1, 0x2d, 0x1a, 0x03, 0x74, 0xa3, 0x85, 0xeb, 0x58, 0xfa, 0xde, 0x07, 0x3e, + 0x04, 0x87, 0xdc, 0x92, 0x17, 0x6c, 0x48, 0xc3, 0x6b, 0x7a, 0x2b, 0x34, 0x7a, 0x0f, + 0x96, 0x87, 0x5a, 0x31, 0x2a, 0xd5, 0x17, 0x9d, 0xa3, 0xfc, 0x81, 0x9c, 0xf0, 0xd4, + 0x8a, 0xb1, 0x46, 0xec, 0x2a, 0x2d, 0xd1, 0x45, 0xd7, 0x8d, 0x9d, 0x9f, 0x88, 0x84, + 0x82, 0x16, 0x55, 0x7d, 0x6e, 0x28, 0x30, 0x33, 0x56, 0xea, 0xfb, 0x2d, 0xbb, 0xe4, + 0xfd, 0x12, 0x24, 0x71, 0x37, 0x31, 0x73, 0x0e, 0xae, 0x6f, 0x52, 0x62, 0x5a, 0x59, + 0xe5, 0xb6, 0x06, 0xd2, 0xb2, 0x77, 0xe4, 0x09, 0x7e, 0x4f, 0x54, 0x24, 0x56, 0x84, + 0xeb, 0x3b, 0x64, 0xf5, 0x4d, 0xf6, 0x69, 0x7d, 0x6f, 0x39, 0x82, 0xba, 0xc4, 0x98, + 0xdf, 0x5a, 0x14, 0x43, 0x4f, 0x2e, 0x51, 0xab, 0x4c, 0xc2, 0x9d, 0x6f, 0x31, 0x28, + 0x8f, 0xf6, 0x67, 0x80, 0xb7, 0x89, 0xa8, 0x30, 0x6b, 0x20, 0xc6, 0x55, 0x3a, 0x52, + 0x46, 0x35, 0xb6, 0xec, 0xb6, 0x79, 0xe5, 0x03, 0x09, 0x54, 0x02, 0x96, 0xed, 0xef, + 0x53, 0x83, 0x31, 0x63, 0xc4, 0xa2, 0x86, 0x00, 0xd1, 0xca, 0xa8, 0x43, 0x7e, 0x6f, + 0xb9, 0xce, 0xc4, 0xb9, 0xea, 0xf5, 0x66, 0xe1, 0x7b, 0xe8, 0xf8, 0xcc, 0x34, 0xcd, + 0xdb, 0x35, 0x88, 0xce, 0xb2, 0xbf, 0xe8, 0x8c, 0xc3, 0xee, 0xb4, 0x1b, 0x92, 0x63, + 0x1f, 0x13, 0xc5, 0xeb, 0xa6, 0x86, 0x30, 0xbf, 0xa5, 0x35, 0x31, 0x30, 0x06, 0x57, + 0x49, 0x44, 0x83, 0x3c, 0xea, 0x59, 0xd9, 0xb2, 0xd1, 0x94, 0xd8, 0xc1, 0xac, 0xc1, + 0xa4, 0x17, 0x62, 0xf8, 0x98, 0x09, 0xf7, 0x8d, 0xab, 0xe9, 0x9b, 0x95, 0xb5, 0xdd, + 0xbe, 0xd1, 0xd0, 0x01, 0x03, 0x26, 0x84, 0x4f, 0x23, 0x04, 0x85, 0x84, 0xaa, 0x14, + 0x66, 0x0f, 0xe2, 0x54, 0x9c, 0xbe, 0xe9, 0xaf, 0x4b, 0x63, 0xdd, 0xde, 0x1c, 0xec, + 0x9f, 0x8d, 0x7c, 0xcb, 0xa6, 0x2a, 0x39, 0xf2, 0xf4, 0x48, 0x04, 0x96, 0xa1, 0x0f, + 0x17, 0xe9, 0xf9, 0x12, 0xc6, 0xc0, 0xa1, 0x3d, 0xbd, 0x90, 0x32, 0x60, 0x42, 0x89, + 0x4b, 0xcd, 0xf6, 0xa8, 0x07, 0x32, 0xc5, 0xfb, 0x03, 0x09, 0xee, 0xbd, 0xc4, 0x34, + 0x0c, 0x5e, 0xb5, 0x66, 0x41, 0x7c, 0xc6, 0xc8, 0xa6, 0xa6, 0x09, 0xdf, 0x5b, 0x41, + 0xc6, 0xc2, 0x95, 0xd6, 0x47, 0x3d, 0xab, 0xc7, 0x4c, 0xbb, 0x34, 0xb5, 0x5b, 0xa7, + 0x9a, 0x89, 0x46, 0x35, 0xa9, 0x00, 0x93, 0x27, 0xcc, 0x1e, 0x6d, 0x3e, 0x42, 0xba, + 0x3c, 0xba, 0xfb, 0x32, 0x1b, 0xc0, 0xb2, 0xee, 0x28, 0xe4, 0x1e, 0xf3, 0xba, 0xec, + 0xbe, 0x50, 0x46, 0x72, 0xf6, 0xe9, 0x35, 0x08, 0x66, 0x90, 0x87, 0xd5, 0x03, 0x34, + 0x36, 0x41, 0xb5, 0x9b, 0x90, 0x6a, 0x56, 0x4b, 0x7b, 0x67, 0x53, 0xd6, 0x19, 0xee, + 0xc4, 0xf5, 0xe8, 0x10, 0x62, 0x0e, 0x7b, 0x50, 0x65, 0x1a, 0xb6, 0x5e, 0x0a, 0x3d, + 0xbb, 0x1d, 0x0a, 0xb7, 0x72, 0x1c, 0x5b, 0xf0, 0xd5, 0x40, 0xe1, 0x30, 0x2d, 0x8c, + 0xce, 0x27, 0x07, 0x71, 0x91, 0x99, 0xfa, 0xa5, 0x32, 0x11, 0x06, 0xab, 0x06, 0x81, + 0x6a, 0x8c, 0x04, 0x6e, 0x47, 0x8b, 0xd5, 0xc3, 0xb4, 0x8f, 0xe6, 0x65, 0xc8, 0xd5, + 0x92, 0xfb, 0x30, 0x6b, 0xa9, 0x37, 0x10, 0x23, 0x30, 0xe4, 0x56, 0x48, 0xf1, 0xc1, + 0x6f, 0x3d, 0x1a, 0x96, 0x0f, 0x2f, 0x5f, 0x8c, 0x4d, 0x00, 0x12, 0x07, 0x8f, 0x9c, + 0xfd, 0xf6, 0xb6, 0x6d, 0xe9, 0x61, 0xca, 0x2e, 0x14, 0x0d, + ], + ock: [ + 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, + 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, + 0x8b, 0xb3, 0x29, 0x3d, + ], + op: [ + 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, + 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, + 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, + 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, + 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, + ], + c_out: [ + 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, + 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, + 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, + 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, + 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, + 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xdc, 0x10, 0x95, 0x20, 0x57, 0xc4, 0xbe, 0xaa, 0xd8, 0xaf, 0x37, 0xce, 0x4e, 0xee, + 0x9b, 0x10, 0xed, 0x84, 0xf4, 0x6b, 0xad, 0xd4, 0x8e, 0x0a, 0x22, 0x9b, 0xe8, 0x41, + 0x54, 0xa9, 0xbf, 0x75, 0x6b, 0xe0, 0x2e, 0xcf, 0xa9, 0xad, 0x6d, 0x9c, 0x02, 0xc8, + 0xf9, 0x54, 0xcb, 0x15, 0x71, 0x7b, 0x79, 0x46, 0x1f, 0x00, 0x4b, 0xf1, 0xbc, 0x5c, + 0x7e, 0x3f, 0xda, 0x73, 0x53, 0x7c, 0x1a, 0x0a, + ], + ovk: [ + 0x97, 0x74, 0x85, 0xcd, 0xdf, 0xbe, 0xd5, 0x93, 0x2f, 0x50, 0x7b, 0x79, 0x94, 0x7a, + 0xdb, 0x2f, 0xad, 0x37, 0x61, 0x5a, 0xa7, 0x17, 0xdb, 0x5f, 0x29, 0x80, 0x99, 0xf2, + 0x0f, 0x26, 0x3b, 0x35, + ], + default_d: [ + 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, + ], + default_pk_d: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, + ], + v: 2111628168871420429, + rseed: [ + 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, + 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, + 0x3b, 0xd5, 0xbc, 0x87, + ], + asset: [ + 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, + 0x84, 0xef, 0xd9, 0x2c, 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, + 0x4f, 0x95, 0x22, 0xb2, + ], + memo: [ + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, 0x33, 0x49, 0x4a, 0x7a, 0xe1, 0x30, 0xfe, 0x86, 0xe8, 0xf8, + 0x18, 0xf9, 0x26, 0x1a, 0x2d, 0xad, 0xb4, 0x12, 0x52, 0x29, 0xba, 0x0f, 0xfc, 0x0e, + 0x70, 0x90, 0x32, 0x44, 0x30, 0xb5, 0x21, 0xa9, + ], + cv_net: [ + 0xba, 0x69, 0x9c, 0xe4, 0x21, 0x41, 0x85, 0x30, 0x94, 0xe2, 0x84, 0x00, 0x50, 0x17, + 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, + 0xbc, 0xca, 0x68, 0xb4, + ], + nf_old: [ + 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, + 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, + 0xbc, 0xf8, 0x63, 0x37, + ], + cmx: [ + 0x20, 0x43, 0xa5, 0x58, 0x39, 0x9e, 0x2e, 0xed, 0x91, 0xd9, 0x5d, 0x32, 0xe6, 0xd6, + 0x7c, 0x93, 0xdb, 0x08, 0xe2, 0x15, 0x15, 0x02, 0x85, 0x8d, 0x8b, 0x77, 0x54, 0x87, + 0x5f, 0x10, 0x89, 0x32, + ], + esk: [ + 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, 0x39, 0x16, 0x0f, 0xe5, + 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, 0xe0, 0xd2, 0x9b, 0x35, + 0x9a, 0xc4, 0xfa, 0x2c, + ], + ephemeral_key: [ + 0x10, 0x0d, 0xf0, 0x1d, 0x49, 0x86, 0x01, 0x21, 0x8a, 0x28, 0x6b, 0x8f, 0x4e, 0x54, + 0xda, 0x9b, 0x3f, 0x14, 0x5c, 0x34, 0x70, 0xa9, 0xdb, 0xc4, 0x14, 0x48, 0x0a, 0xa8, + 0xf2, 0xf4, 0x90, 0x9c, + ], + shared_secret: [ + 0x93, 0x68, 0xdd, 0x4f, 0x2a, 0xf6, 0x23, 0x34, 0xb8, 0x85, 0xb9, 0x6b, 0xc4, 0xc3, + 0x8f, 0x10, 0x3a, 0xec, 0x25, 0x6b, 0xed, 0xc2, 0x8b, 0x5e, 0x2e, 0x10, 0x36, 0x4c, + 0xdd, 0xf3, 0x84, 0xa4, + ], + k_enc: [ + 0x7a, 0xff, 0xfc, 0x6e, 0xae, 0x5d, 0x56, 0xb2, 0x7b, 0x86, 0xdb, 0x9e, 0xc8, 0xae, + 0xc2, 0x70, 0xbb, 0x0a, 0xb7, 0x31, 0x23, 0xfd, 0x2a, 0x0b, 0x83, 0xf4, 0xef, 0x84, + 0xc6, 0x98, 0xe1, 0x67, + ], + p_enc: [ + 0x03, 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, 0x0d, 0x22, + 0x4a, 0xb7, 0xa1, 0x02, 0x4e, 0x1d, 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, + 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, + 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, 0x3b, 0xd5, 0xbc, 0x87, 0xa9, 0x71, 0x5e, 0x65, + 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, 0x84, 0xef, 0xd9, 0x2c, + 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, 0x4f, 0x95, 0x22, 0xb2, + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, 0x33, 0x49, 0x4a, 0x7a, 0xe1, 0x30, 0xfe, 0x86, 0xe8, 0xf8, + 0x18, 0xf9, 0x26, 0x1a, 0x2d, 0xad, 0xb4, 0x12, 0x52, 0x29, 0xba, 0x0f, 0xfc, 0x0e, + 0x70, 0x90, 0x32, 0x44, 0x30, 0xb5, 0x21, 0xa9, + ], + c_enc: [ + 0x45, 0x6b, 0x2b, 0xb8, 0x03, 0xc7, 0xdf, 0xf7, 0xac, 0x82, 0xe6, 0x42, 0xf4, 0xd8, + 0x46, 0x1e, 0x0b, 0x7a, 0x3b, 0x3c, 0x95, 0xa4, 0xcb, 0xf1, 0xc0, 0x6f, 0xeb, 0x93, + 0xa1, 0x8b, 0xeb, 0xa2, 0x9f, 0x2b, 0x8f, 0x12, 0x1a, 0x61, 0x5c, 0xa5, 0x3f, 0xc2, + 0xa7, 0x60, 0x63, 0xb8, 0x0d, 0xaa, 0x71, 0x01, 0x8b, 0x66, 0x3b, 0x7c, 0x46, 0x6d, + 0xb2, 0x63, 0xf9, 0x04, 0x27, 0xd0, 0x11, 0x7f, 0x0b, 0x89, 0x90, 0x6e, 0x98, 0x41, + 0x7f, 0x3e, 0xe8, 0x5a, 0xcc, 0xed, 0xb1, 0x41, 0xfb, 0x10, 0x26, 0xa3, 0xb3, 0xf7, + 0xa4, 0xfd, 0x10, 0x24, 0xf9, 0xc8, 0x08, 0x9a, 0x2e, 0xbe, 0x1a, 0x27, 0x82, 0xf8, + 0xb0, 0xbf, 0x5c, 0x40, 0xb6, 0xd5, 0x2f, 0xfe, 0x38, 0x37, 0xf4, 0xe4, 0x42, 0x52, + 0x13, 0x41, 0xc2, 0x4d, 0x3e, 0x89, 0x55, 0x95, 0x08, 0x86, 0x27, 0x85, 0xea, 0x63, + 0x56, 0xb4, 0xe4, 0x66, 0xc3, 0x25, 0x9c, 0xeb, 0x0d, 0x28, 0x2e, 0x07, 0xbb, 0x35, + 0xdc, 0xf2, 0xd9, 0xa8, 0x62, 0xc7, 0x47, 0x58, 0xd3, 0x83, 0xaa, 0xa2, 0x82, 0xfa, + 0xc4, 0xfa, 0xcf, 0xe5, 0x39, 0xe4, 0xe1, 0xbb, 0xd5, 0x46, 0x8a, 0xcf, 0x25, 0xec, + 0x2b, 0x4b, 0xa5, 0x11, 0x9d, 0xea, 0xed, 0x01, 0x1d, 0x4f, 0x30, 0xb0, 0xc5, 0x82, + 0x01, 0xfe, 0xe1, 0xc6, 0xe4, 0xf6, 0xb5, 0x2e, 0x41, 0xad, 0xfa, 0x5d, 0x6f, 0xda, + 0x94, 0xa5, 0x23, 0x20, 0xe8, 0x3b, 0x80, 0xc6, 0xfc, 0xee, 0xb8, 0x97, 0x89, 0xd8, + 0x79, 0x94, 0xb7, 0xa0, 0x16, 0xec, 0x64, 0xe4, 0x70, 0x78, 0x07, 0xf8, 0xf2, 0xd2, + 0x30, 0x63, 0x10, 0x74, 0x10, 0x9f, 0xc5, 0x9d, 0xe3, 0xe4, 0x37, 0x10, 0xca, 0xe8, + 0x9c, 0xb1, 0x89, 0xa0, 0xa4, 0x64, 0x8b, 0x37, 0x54, 0x5d, 0x25, 0x49, 0x47, 0x95, + 0xa8, 0xdf, 0x3f, 0xfc, 0x7a, 0x3a, 0x21, 0xe3, 0xb9, 0x1c, 0x95, 0x96, 0xe0, 0xd5, + 0x10, 0x5d, 0xf8, 0xad, 0xa9, 0xcf, 0xe9, 0x31, 0x10, 0xb1, 0x9f, 0xf2, 0xaf, 0x83, + 0x03, 0xb5, 0xd2, 0x79, 0x3f, 0xff, 0xd0, 0x4d, 0x8e, 0x02, 0xf7, 0xb9, 0x30, 0x14, + 0x80, 0xdf, 0xd9, 0x35, 0x50, 0x2d, 0x98, 0xe2, 0xf3, 0xc3, 0xe9, 0xe9, 0x5e, 0x64, + 0xe4, 0x96, 0xeb, 0x7d, 0x15, 0xcf, 0x2c, 0x70, 0x11, 0x94, 0xe6, 0x25, 0xde, 0x52, + 0x1a, 0x02, 0x55, 0x20, 0xdf, 0x67, 0xac, 0x2b, 0xa4, 0x3b, 0x9c, 0x4a, 0x6d, 0x77, + 0xb8, 0x6a, 0x40, 0x18, 0x2d, 0x70, 0x31, 0x8b, 0x8f, 0xa3, 0x48, 0xb1, 0x86, 0x47, + 0xd8, 0x4e, 0x0e, 0xe5, 0xf0, 0x56, 0x07, 0xa2, 0xb8, 0xf2, 0x69, 0xe1, 0x86, 0xc7, + 0x94, 0x28, 0xbe, 0xa6, 0x7c, 0xbf, 0x71, 0xda, 0xcc, 0x98, 0xe9, 0xcc, 0x72, 0x5e, + 0x50, 0x53, 0xa4, 0x40, 0xca, 0xa6, 0xca, 0xd2, 0x41, 0xa5, 0x06, 0x28, 0x18, 0x3a, + 0xe9, 0xef, 0x9f, 0x0c, 0xbd, 0xfe, 0xf7, 0x0a, 0x42, 0xe5, 0xb7, 0x97, 0xbc, 0x99, + 0xd9, 0x22, 0xfc, 0xc2, 0x81, 0x37, 0x84, 0xea, 0xe4, 0x48, 0x60, 0x18, 0x0e, 0xf8, + 0xe8, 0x1f, 0x7b, 0x94, 0xf2, 0xad, 0x62, 0x12, 0x8b, 0xb6, 0x1f, 0x10, 0xd5, 0x0c, + 0x9c, 0xad, 0x9d, 0x80, 0x48, 0xd9, 0x78, 0x01, 0x8a, 0x1f, 0x3b, 0xc9, 0x24, 0x28, + 0xf8, 0x9d, 0x7d, 0xdc, 0xe5, 0x45, 0x4b, 0xc4, 0x49, 0x1f, 0xb4, 0xc2, 0xcb, 0x66, + 0x88, 0x35, 0xb2, 0x2f, 0xcc, 0x4d, 0xf2, 0x08, 0xf2, 0x16, 0x64, 0xf7, 0x12, 0x94, + 0xc5, 0xce, 0xd3, 0x3c, 0x8e, 0x11, 0xd4, 0x25, 0xd1, 0x39, 0x85, 0x23, 0xc2, 0x79, + 0x88, 0x3a, 0x38, 0x2f, 0x70, 0xfe, 0xfe, 0xc8, 0x25, 0xc5, 0xe3, 0x50, 0x85, 0xaf, + 0x82, 0xd0, 0xa0, 0xa9, 0xbf, 0x45, 0x11, 0x65, 0x0a, 0x2b, 0xfb, 0xf0, 0xb2, 0x18, + 0x82, 0x10, 0x5e, 0xc6, 0xe5, 0x99, 0x74, 0xd8, 0xd6, 0xce, 0x73, 0x07, 0x8f, 0xb4, + 0xb5, 0x63, 0x4e, 0x85, 0xd7, 0xe2, 0x0a, 0x97, 0xff, 0xb6, 0x5d, 0x4f, 0x5e, 0xaf, + 0x42, 0x63, 0x9b, 0x09, 0xf5, 0xed, 0xa5, 0x9a, 0xb1, 0x04, 0x97, 0x69, 0x95, 0x41, + 0xd1, 0xc8, 0x22, 0x8e, 0xca, 0x31, 0x3f, 0xd0, 0x0a, 0x21, 0xb3, 0x02, 0x7b, 0x40, + 0xd0, 0xc1, 0xfd, 0x4c, 0x2f, 0x0d, 0x97, 0xf1, 0xa9, 0x58, 0xe9, 0x2b, 0x45, 0xd5, + 0xd4, 0xbf, 0xc2, 0xef, 0x18, 0xef, 0xd6, 0xb2, 0x5b, 0x47, 0xa9, 0x4d, 0xae, 0x73, + 0xc3, 0xcf, 0xc9, 0xca, 0xd8, 0xdb, 0x82, 0x3f, 0xbd, 0x74, + ], + ock: [ + 0x9b, 0x8e, 0x79, 0x56, 0x76, 0x38, 0xa2, 0xee, 0x38, 0x72, 0x5a, 0x94, 0x28, 0x99, + 0xa5, 0xa3, 0xbd, 0xd6, 0x88, 0xdb, 0x76, 0x38, 0x99, 0x7c, 0x77, 0x27, 0x6d, 0x27, + 0x0c, 0x87, 0xd2, 0xa3, + ], + op: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, + 0x39, 0x16, 0x0f, 0xe5, 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, + 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, + ], + c_out: [ + 0xe6, 0xe7, 0xa3, 0x48, 0xf3, 0x3a, 0xdd, 0x64, 0x22, 0x87, 0xc5, 0xf8, 0xf0, 0x9a, + 0x5a, 0xae, 0xd7, 0x9d, 0xf6, 0x70, 0xcc, 0x29, 0x74, 0x78, 0xc2, 0x27, 0x11, 0xe3, + 0x4e, 0xfa, 0x00, 0x88, 0x1d, 0x34, 0xb8, 0x7c, 0x0f, 0x69, 0xcb, 0x55, 0xd9, 0x1d, + 0x91, 0x1d, 0x2d, 0x84, 0x1e, 0x5e, 0xf6, 0x40, 0x38, 0x24, 0xdc, 0x9d, 0x7c, 0x55, + 0x1c, 0xdb, 0xae, 0xb4, 0xa6, 0xfb, 0x46, 0x8e, 0xc0, 0x39, 0xbc, 0x84, 0x17, 0x79, + 0xa0, 0xd7, 0xbf, 0xc3, 0x1b, 0xe2, 0x0b, 0x34, 0xee, 0x25, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xb6, 0x6c, 0x73, 0x33, 0x75, 0xda, 0xc6, 0xff, 0xcc, 0x98, 0xf5, 0x0f, 0x3a, 0xf0, + 0xb0, 0x76, 0x05, 0x53, 0xfe, 0x98, 0xed, 0x61, 0xff, 0xa4, 0x93, 0xea, 0xe6, 0x8d, + 0xf0, 0xb3, 0x33, 0x4e, 0xe8, 0xd4, 0x39, 0x37, 0xb7, 0xdb, 0x8e, 0xbb, 0xfe, 0xbd, + 0x54, 0x8a, 0x28, 0x02, 0x51, 0xea, 0x87, 0xaa, 0x5d, 0x8c, 0xa5, 0x36, 0x86, 0x1b, + 0x38, 0x4f, 0x20, 0x86, 0x9f, 0x8f, 0xe8, 0x01, + ], + ovk: [ + 0xe9, 0x4c, 0x15, 0x24, 0x5f, 0x1a, 0x95, 0x88, 0x40, 0xba, 0x3f, 0x38, 0x0a, 0x4d, + 0x20, 0xf1, 0x18, 0x4e, 0x77, 0x82, 0x7d, 0xe3, 0xff, 0x8f, 0x3d, 0x73, 0x45, 0x9a, + 0xfe, 0x24, 0x1f, 0x72, + ], + default_d: [ + 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, + ], + default_pk_d: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, + ], + v: 16065731808124965111, + rseed: [ + 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, + 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, + 0x71, 0x8c, 0x29, 0xdd, + ], + asset: [ + 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, + 0x01, 0xe2, 0x99, 0x0a, 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, + 0xfd, 0x7d, 0x05, 0x8a, + ], + memo: [ + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, 0x22, 0xa7, 0xc2, 0xe0, 0x01, 0x3e, 0xa4, 0x7d, 0x0b, 0xdd, + 0x42, 0xd6, 0x99, 0x04, 0x66, 0x64, 0x9a, 0x90, 0x5c, 0x68, 0x4c, 0x32, 0x51, 0x71, + 0x6d, 0x61, 0xf7, 0x60, 0xd5, 0x3d, 0xe6, 0xe3, + ], + cv_net: [ + 0x0a, 0x1f, 0x28, 0x15, 0xb7, 0xaf, 0xe2, 0x19, 0x06, 0x87, 0x15, 0xfc, 0x76, 0x6b, + 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, + 0x34, 0x5e, 0x46, 0x98, + ], + nf_old: [ + 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, + 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, + 0xb6, 0xf6, 0x4c, 0x26, + ], + cmx: [ + 0xf0, 0x32, 0x44, 0xf8, 0x87, 0xe7, 0x5e, 0x45, 0x2f, 0xf0, 0x06, 0x89, 0x64, 0x44, + 0x2c, 0x9b, 0xc1, 0x03, 0x48, 0xec, 0xa6, 0xc2, 0xbc, 0x46, 0xcc, 0x85, 0xda, 0x5d, + 0x34, 0x0b, 0x43, 0x35, + ], + esk: [ + 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, 0xef, 0x08, 0xbd, 0xf6, + 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, 0xf5, 0x3b, 0x57, 0xc3, + 0x45, 0xa9, 0x87, 0x2f, + ], + ephemeral_key: [ + 0xa5, 0xc8, 0x0a, 0x29, 0xf2, 0xec, 0xdd, 0xd7, 0x01, 0x96, 0xef, 0x45, 0x9e, 0xd5, + 0x03, 0xc4, 0xb3, 0xc2, 0x22, 0x8d, 0x10, 0xcc, 0xbc, 0xad, 0x9a, 0x28, 0x23, 0x30, + 0x07, 0x7b, 0xca, 0x0c, + ], + shared_secret: [ + 0x37, 0x14, 0x15, 0xfc, 0x1e, 0x98, 0x42, 0xa1, 0x26, 0xa3, 0x7a, 0xa7, 0x7b, 0x8f, + 0x0f, 0x1a, 0xb6, 0x48, 0xa3, 0xf7, 0x43, 0x57, 0x34, 0x89, 0x6f, 0x07, 0x59, 0x52, + 0xe7, 0xd1, 0x60, 0x17, + ], + k_enc: [ + 0xd7, 0x36, 0xf0, 0x3c, 0x81, 0x2d, 0x9b, 0xf9, 0x54, 0xff, 0xd2, 0x41, 0x84, 0x07, + 0xf3, 0x36, 0xa5, 0xf9, 0x69, 0x8b, 0x62, 0x85, 0x23, 0x2f, 0x5c, 0x85, 0xf0, 0xd1, + 0x1d, 0x5e, 0x9d, 0x0a, + ], + p_enc: [ + 0x03, 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, 0xf7, 0x90, + 0xfb, 0xa7, 0xf5, 0xf1, 0xf4, 0xde, 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, + 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, + 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, 0x71, 0x8c, 0x29, 0xdd, 0xdf, 0xfd, 0x79, 0xa9, + 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, 0x01, 0xe2, 0x99, 0x0a, + 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, 0xfd, 0x7d, 0x05, 0x8a, + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, 0x22, 0xa7, 0xc2, 0xe0, 0x01, 0x3e, 0xa4, 0x7d, 0x0b, 0xdd, + 0x42, 0xd6, 0x99, 0x04, 0x66, 0x64, 0x9a, 0x90, 0x5c, 0x68, 0x4c, 0x32, 0x51, 0x71, + 0x6d, 0x61, 0xf7, 0x60, 0xd5, 0x3d, 0xe6, 0xe3, + ], + c_enc: [ + 0xfc, 0x90, 0xcb, 0xe1, 0xcd, 0x9f, 0x59, 0x9a, 0x1a, 0x24, 0xc7, 0xa3, 0xea, 0xf6, + 0x07, 0xd9, 0x13, 0xbf, 0x48, 0xbd, 0xc1, 0xa4, 0x6d, 0xf7, 0xb1, 0x74, 0x7f, 0x12, + 0x60, 0x64, 0x49, 0x4b, 0xf5, 0x39, 0x61, 0xe9, 0xa5, 0xa2, 0xb9, 0x69, 0x80, 0x57, + 0x63, 0x44, 0x2e, 0x2c, 0x38, 0x8d, 0x21, 0x2d, 0x74, 0x84, 0x6e, 0x57, 0x27, 0x87, + 0x2d, 0x06, 0x3f, 0xc9, 0x94, 0xa4, 0x4f, 0x9e, 0xb6, 0x55, 0x25, 0xd6, 0x8f, 0x98, + 0x24, 0xa6, 0x03, 0x75, 0xfe, 0x43, 0xc0, 0x5f, 0x08, 0xfe, 0x45, 0x42, 0xa7, 0xe4, + 0x0c, 0x03, 0x8d, 0xe7, 0x10, 0x85, 0x01, 0x17, 0x95, 0x1b, 0x9a, 0x32, 0x1e, 0xea, + 0x4f, 0x8c, 0x91, 0xc0, 0x1d, 0x39, 0xdb, 0xb5, 0xd4, 0x12, 0x40, 0xf8, 0xb1, 0xb1, + 0xdb, 0xb3, 0x3f, 0x45, 0x87, 0x87, 0xdb, 0x8c, 0xda, 0x06, 0x9b, 0x64, 0x5a, 0x76, + 0x38, 0xc2, 0xec, 0xca, 0xd3, 0xd9, 0xa7, 0x39, 0xd6, 0x4c, 0x9a, 0xd5, 0xd5, 0xb3, + 0xa0, 0x24, 0x55, 0xa4, 0xec, 0xd6, 0x96, 0x7c, 0xf3, 0xb3, 0x3b, 0xf0, 0x4e, 0xf6, + 0xdd, 0x88, 0x10, 0xe1, 0x0c, 0x25, 0x86, 0xf7, 0x89, 0x32, 0x44, 0xea, 0x72, 0x80, + 0xd1, 0x34, 0xcf, 0x37, 0xb3, 0xdc, 0x0c, 0x32, 0x82, 0x3b, 0x1a, 0x29, 0xc5, 0x0c, + 0xa6, 0x48, 0x31, 0xd8, 0x4e, 0xbd, 0xf5, 0xe0, 0x1c, 0x14, 0xca, 0x36, 0x05, 0xbe, + 0x02, 0xf1, 0x5f, 0x31, 0x57, 0x90, 0xf7, 0x4e, 0x20, 0x57, 0x7f, 0x92, 0x39, 0x51, + 0x2f, 0xbd, 0xdd, 0x67, 0x63, 0x77, 0xae, 0x50, 0xc3, 0xfe, 0x71, 0xc9, 0x30, 0xa8, + 0x29, 0x57, 0xd1, 0x54, 0x70, 0xeb, 0x1b, 0x55, 0xb2, 0x0c, 0xe5, 0x02, 0x35, 0x64, + 0xfe, 0xa7, 0xe1, 0x81, 0xbe, 0x04, 0xa9, 0x33, 0xa7, 0xa3, 0xa1, 0x11, 0x89, 0x4d, + 0xec, 0xf7, 0x2a, 0x56, 0x54, 0xcb, 0x4e, 0xac, 0x32, 0xe1, 0xd5, 0x96, 0xad, 0x99, + 0x1a, 0x2f, 0x4c, 0x62, 0xe8, 0xe2, 0x82, 0x57, 0x13, 0x7b, 0xcb, 0xa5, 0x03, 0xdc, + 0x91, 0xed, 0x9e, 0x90, 0xb3, 0x08, 0xcd, 0xa5, 0xcc, 0xcc, 0xc9, 0xd1, 0x4e, 0xa6, + 0xd0, 0x3b, 0x3d, 0xec, 0xa1, 0x57, 0xd5, 0x30, 0xde, 0x63, 0x1e, 0x1e, 0x45, 0x8f, + 0x6a, 0x60, 0x8e, 0x1f, 0x9d, 0x57, 0x9b, 0x6e, 0xe6, 0x00, 0x5c, 0xd0, 0xa8, 0xc3, + 0xe2, 0xdf, 0x89, 0x46, 0x8a, 0xcf, 0xb4, 0x36, 0xcb, 0x59, 0x84, 0x56, 0xf0, 0x38, + 0x95, 0x5d, 0xc6, 0xb4, 0x07, 0xec, 0x33, 0x00, 0xa5, 0xcf, 0xcd, 0xc8, 0x45, 0x47, + 0xe3, 0xef, 0xe9, 0xfc, 0xa1, 0x7e, 0xd2, 0xc2, 0x74, 0xf0, 0x03, 0x0b, 0x63, 0xcc, + 0x42, 0xe2, 0x38, 0x94, 0xa5, 0xf2, 0x53, 0x66, 0xcb, 0xc3, 0xbf, 0xcb, 0x77, 0x2d, + 0x04, 0x17, 0xf6, 0x24, 0x4b, 0x2f, 0xd8, 0x17, 0xc4, 0xc6, 0x79, 0x06, 0xc3, 0x38, + 0x4d, 0x69, 0xd7, 0x93, 0xef, 0xca, 0x6e, 0x5d, 0x6a, 0xf2, 0x5e, 0x4e, 0xbc, 0x0f, + 0x53, 0x56, 0xeb, 0x74, 0x28, 0x85, 0x19, 0xe8, 0xf4, 0x49, 0x38, 0xeb, 0xf9, 0xb2, + 0x5b, 0xe5, 0x85, 0xe1, 0x35, 0x1f, 0x62, 0x59, 0x6c, 0x31, 0x79, 0xca, 0xe4, 0x5e, + 0x75, 0x49, 0xd7, 0xfb, 0xb5, 0x91, 0x3b, 0xe9, 0xc3, 0xba, 0xa5, 0x7c, 0xab, 0x7c, + 0xd4, 0xb5, 0x67, 0x12, 0x8d, 0x1b, 0xa5, 0x20, 0x31, 0xd7, 0xd5, 0xa5, 0xbd, 0x69, + 0xde, 0x61, 0x4a, 0xbb, 0x8c, 0xa3, 0x8a, 0x94, 0x51, 0xcd, 0x1b, 0xad, 0xd9, 0x71, + 0xb3, 0xf1, 0xb0, 0xb5, 0x0c, 0x7f, 0x21, 0xbf, 0xc4, 0x23, 0x04, 0xa4, 0xa5, 0x3e, + 0x0d, 0x55, 0x92, 0x0d, 0xa0, 0x53, 0x27, 0x14, 0x79, 0x13, 0x45, 0xfb, 0x07, 0x4c, + 0x66, 0xc4, 0xb7, 0xc9, 0x89, 0x28, 0x30, 0xf9, 0x62, 0x09, 0xb8, 0x1c, 0x26, 0xd1, + 0x74, 0xf8, 0xa9, 0x33, 0xc3, 0x77, 0x9d, 0x97, 0x88, 0x55, 0x3f, 0x6e, 0xeb, 0x21, + 0xf7, 0xdb, 0x57, 0x78, 0xf4, 0xf8, 0x17, 0x4c, 0xb4, 0x6f, 0x71, 0xfd, 0xdc, 0x4b, + 0xe4, 0xd8, 0x70, 0x3e, 0xbf, 0xbc, 0xd2, 0xa7, 0x72, 0x89, 0xee, 0xfa, 0x72, 0x76, + 0x56, 0x74, 0xdb, 0xf0, 0x43, 0xd4, 0x25, 0x8c, 0xcc, 0x4a, 0x2f, 0x16, 0x5c, 0x02, + 0xdc, 0xdb, 0x57, 0x2a, 0x70, 0x9d, 0x58, 0x45, 0x83, 0xe9, 0xde, 0x07, 0x8f, 0x1b, + 0x6c, 0x0c, 0x67, 0xf2, 0x8f, 0x17, 0xae, 0x52, 0x30, 0x19, 0x83, 0xf7, 0x9c, 0x28, + 0x83, 0x95, 0xa3, 0x99, 0x63, 0x65, 0xa2, 0x0c, 0x22, 0x9e, + ], + ock: [ + 0xb9, 0x64, 0x28, 0x18, 0x81, 0x8d, 0x69, 0x17, 0x6d, 0x6c, 0xe6, 0x08, 0x88, 0x7d, + 0x75, 0x70, 0x58, 0xc7, 0x35, 0x42, 0x74, 0xac, 0xa2, 0xb8, 0x7b, 0x50, 0xf7, 0xa6, + 0x38, 0x52, 0x51, 0x1b, + ], + op: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, + 0xef, 0x08, 0xbd, 0xf6, 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, + 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, + ], + c_out: [ + 0xa2, 0xd6, 0x5e, 0x96, 0x7e, 0x98, 0x89, 0x0e, 0x9c, 0x42, 0xf9, 0xb3, 0x4b, 0xf8, + 0x45, 0xfb, 0x8e, 0xaa, 0xf9, 0x20, 0x45, 0x0b, 0x29, 0xec, 0x06, 0x16, 0xb3, 0xf0, + 0x82, 0xea, 0x90, 0x8c, 0x66, 0x87, 0xf4, 0xf9, 0x74, 0x1a, 0xe8, 0xab, 0x81, 0x30, + 0x15, 0x35, 0xfd, 0x10, 0x30, 0x35, 0x7a, 0x78, 0xb2, 0x07, 0xf1, 0xc4, 0x42, 0x77, + 0xf5, 0x03, 0xdb, 0x42, 0xa2, 0xc4, 0xdd, 0x20, 0x25, 0x33, 0x2f, 0x49, 0x5e, 0x88, + 0x31, 0x1b, 0x4c, 0x2f, 0x66, 0xb6, 0x07, 0x29, 0x04, 0x89, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x8c, 0x45, 0x43, 0xe1, 0x1f, 0x9f, 0x30, 0x7e, 0xc9, 0x04, 0x31, 0x61, 0x29, 0x46, + 0xfb, 0x01, 0x81, 0xb3, 0x6e, 0x1b, 0x52, 0xdb, 0x43, 0x1e, 0x6d, 0xf9, 0x38, 0x8c, + 0xac, 0xd3, 0x08, 0xe8, 0x99, 0xd9, 0x3f, 0x70, 0xad, 0x2a, 0xea, 0xec, 0x99, 0x5e, + 0xcc, 0xe1, 0x80, 0x1c, 0x61, 0x56, 0xe2, 0x3e, 0xc4, 0x1b, 0x1a, 0xe1, 0xcd, 0x2f, + 0xd6, 0xe3, 0x9b, 0x69, 0x98, 0x2f, 0x46, 0x33, + ], + ovk: [ + 0x01, 0x76, 0xae, 0x33, 0x93, 0x25, 0xd5, 0xa5, 0x88, 0xda, 0x57, 0x96, 0xfa, 0xae, + 0x5b, 0xab, 0x7c, 0x82, 0x97, 0x7c, 0x0f, 0xf7, 0x97, 0x09, 0x3e, 0x2c, 0x1f, 0x3a, + 0xe8, 0x55, 0xf6, 0x5a, + ], + default_d: [ + 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, + ], + default_pk_d: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, + ], + v: 3775288302605163507, + rseed: [ + 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, + 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, + 0x3e, 0xcd, 0xd7, 0x99, + ], + asset: [ + 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, + 0x5a, 0x31, 0xf6, 0x2e, 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, + 0xb4, 0x42, 0x68, 0x3c, + ], + memo: [ + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, 0x00, 0x8b, 0x0d, 0xad, 0xde, 0xec, 0xaa, 0x60, 0x44, 0x70, + 0xbb, 0xe0, 0xfa, 0xda, 0x25, 0x5d, 0x29, 0x0e, 0x92, 0xb1, 0x90, 0xc2, 0xc2, 0xd8, + 0xc2, 0xde, 0xe5, 0x45, 0x5d, 0x1f, 0xa9, 0xa9, + ], + cv_net: [ + 0xde, 0x2b, 0xfc, 0x89, 0x5b, 0xa8, 0xb5, 0x43, 0x03, 0x93, 0x43, 0x4e, 0x20, 0x92, + 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, + 0x2d, 0xda, 0x71, 0x92, + ], + nf_old: [ + 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, + 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, + 0x1d, 0x40, 0x9b, 0x33, + ], + cmx: [ + 0xf5, 0x3a, 0x98, 0x99, 0xcd, 0x37, 0xf6, 0x2c, 0x94, 0x85, 0x84, 0xb9, 0x67, 0x7c, + 0x78, 0x4c, 0x73, 0x48, 0x43, 0x40, 0x1a, 0x3a, 0x61, 0x0a, 0xcb, 0x28, 0x2f, 0x04, + 0x30, 0xfd, 0x18, 0x3c, + ], + esk: [ + 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, 0xa9, 0x19, 0xa2, 0x06, + 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, 0x25, 0xec, 0xff, 0x47, + 0x72, 0x16, 0x8c, 0x05, + ], + ephemeral_key: [ + 0xc1, 0xce, 0x25, 0xfb, 0x89, 0xe5, 0xca, 0x89, 0x97, 0xf9, 0xb4, 0xbb, 0x0e, 0x1e, + 0xfb, 0xcc, 0x1a, 0x8c, 0xbf, 0x44, 0xec, 0xfd, 0x33, 0x2c, 0x6c, 0x5c, 0x17, 0x3b, + 0xb1, 0x1f, 0xb5, 0x87, + ], + shared_secret: [ + 0x2e, 0xe5, 0x69, 0xce, 0xb3, 0xfd, 0xb8, 0x67, 0xa5, 0xd8, 0x4c, 0x92, 0x68, 0x24, + 0xef, 0x54, 0x9f, 0x2d, 0xd2, 0x8f, 0x8b, 0x04, 0x8d, 0x67, 0xd0, 0x28, 0x81, 0x7d, + 0xbf, 0xf5, 0xd2, 0xb1, + ], + k_enc: [ + 0x41, 0x4d, 0x80, 0x67, 0xc9, 0xfe, 0xbd, 0x5e, 0xbc, 0xd9, 0xae, 0x8c, 0x05, 0x99, + 0x4e, 0x3b, 0x06, 0x85, 0xc8, 0x86, 0x6f, 0x88, 0x95, 0x94, 0xc3, 0x74, 0xb3, 0x75, + 0xac, 0x2c, 0x6d, 0x24, + ], + p_enc: [ + 0x03, 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, 0xf3, 0xdb, + 0x77, 0x79, 0xb5, 0x84, 0x64, 0x34, 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, + 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, + 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, 0x3e, 0xcd, 0xd7, 0x99, 0xa6, 0x33, 0x05, 0x44, + 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, 0x5a, 0x31, 0xf6, 0x2e, + 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0xb4, 0x42, 0x68, 0x3c, + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, 0x00, 0x8b, 0x0d, 0xad, 0xde, 0xec, 0xaa, 0x60, 0x44, 0x70, + 0xbb, 0xe0, 0xfa, 0xda, 0x25, 0x5d, 0x29, 0x0e, 0x92, 0xb1, 0x90, 0xc2, 0xc2, 0xd8, + 0xc2, 0xde, 0xe5, 0x45, 0x5d, 0x1f, 0xa9, 0xa9, + ], + c_enc: [ + 0xbc, 0x8a, 0x16, 0xfd, 0x57, 0xbc, 0x03, 0x60, 0x59, 0xe5, 0x4d, 0xc2, 0xbc, 0xfa, + 0xad, 0x9c, 0xc1, 0xfa, 0xe8, 0xcb, 0x2b, 0xe2, 0xa0, 0xc8, 0x5e, 0x81, 0x6c, 0x67, + 0xfd, 0xcd, 0x0b, 0x93, 0xe6, 0xa1, 0xed, 0xc8, 0x3b, 0xfa, 0xc4, 0x1e, 0xb4, 0x19, + 0x1c, 0x56, 0x4b, 0xac, 0x58, 0x01, 0x62, 0x92, 0x2d, 0x88, 0x25, 0x30, 0x28, 0xeb, + 0x88, 0xed, 0x46, 0xbf, 0x24, 0x2d, 0x82, 0x28, 0x6c, 0xb0, 0xa5, 0x66, 0xce, 0x01, + 0x18, 0x09, 0x4c, 0x90, 0x8f, 0xc2, 0x68, 0xb3, 0x2b, 0xcb, 0xdc, 0x4c, 0x22, 0x82, + 0xc5, 0x24, 0x2a, 0x65, 0x15, 0x48, 0x8b, 0x83, 0x3d, 0x29, 0x8e, 0x49, 0xda, 0x33, + 0x3a, 0xdd, 0x96, 0xc9, 0x9b, 0x98, 0xac, 0x06, 0x7f, 0x21, 0x41, 0x28, 0x9a, 0xcd, + 0x89, 0x49, 0x64, 0xfc, 0xf8, 0x94, 0xc9, 0x26, 0xf1, 0x81, 0xb1, 0x19, 0x85, 0x68, + 0xb1, 0xdd, 0x6f, 0x5e, 0xd1, 0x22, 0xdc, 0x70, 0x44, 0xad, 0x96, 0x76, 0xa7, 0xc5, + 0xae, 0x8e, 0xa9, 0x0f, 0x64, 0xbc, 0x59, 0x09, 0x36, 0xe0, 0xdf, 0x53, 0x1c, 0x1b, + 0x94, 0xb7, 0x35, 0xcd, 0x7b, 0x18, 0x73, 0xc8, 0x51, 0x6f, 0xea, 0x83, 0x64, 0x91, + 0x40, 0xbc, 0xbb, 0x9b, 0x42, 0xea, 0x6c, 0xb7, 0xaf, 0x67, 0xdc, 0x2d, 0xdb, 0xb4, + 0x7a, 0xb2, 0x25, 0xe7, 0x98, 0x29, 0xcd, 0xaf, 0x77, 0x04, 0xfb, 0x56, 0x5b, 0x43, + 0x91, 0x76, 0xf3, 0x35, 0xe4, 0x2b, 0x64, 0xc1, 0x6d, 0xdf, 0xe0, 0x88, 0x45, 0x38, + 0xbf, 0x43, 0x33, 0xe3, 0x2c, 0xa1, 0xe6, 0x27, 0x41, 0xc3, 0xe7, 0x4c, 0x8f, 0xaa, + 0xde, 0x0d, 0x89, 0xfa, 0x10, 0x30, 0xcd, 0x8e, 0xfd, 0x20, 0x22, 0x3e, 0x41, 0xc3, + 0xfc, 0xca, 0xaa, 0xe7, 0x76, 0xe6, 0x8e, 0xe8, 0x40, 0x56, 0x6f, 0x4d, 0x13, 0xc1, + 0xc9, 0xd5, 0xcb, 0xbe, 0xcf, 0xa7, 0x49, 0x9d, 0x43, 0x12, 0x7c, 0xe8, 0xfd, 0x83, + 0xdb, 0x6e, 0x89, 0x67, 0x90, 0x32, 0x25, 0x24, 0x87, 0x21, 0x40, 0x0d, 0x5e, 0x3e, + 0xc0, 0xc1, 0x8e, 0x10, 0xf5, 0xe6, 0x6e, 0x10, 0x17, 0x0c, 0xb3, 0x74, 0x48, 0x22, + 0x4a, 0xde, 0x39, 0x9f, 0x1d, 0x74, 0xa2, 0x16, 0x7d, 0x9f, 0xdb, 0xfe, 0x36, 0xe1, + 0x28, 0xe4, 0x8c, 0x01, 0x62, 0x61, 0x16, 0xc1, 0xa2, 0xdf, 0x3c, 0xb0, 0x23, 0xd8, + 0x0a, 0xed, 0x9b, 0xfc, 0x02, 0x71, 0xb8, 0x1f, 0xf9, 0x79, 0x81, 0x01, 0x6f, 0xff, + 0x19, 0x61, 0x08, 0x88, 0x8b, 0xcb, 0xca, 0x84, 0x5b, 0x5d, 0x97, 0x1b, 0xd5, 0x4f, + 0x49, 0x7d, 0x3f, 0x3a, 0x09, 0x29, 0x9e, 0x56, 0x50, 0xd3, 0x26, 0xd8, 0x9b, 0x9a, + 0x5e, 0xff, 0x3e, 0xbd, 0x27, 0x39, 0x34, 0xc4, 0x9f, 0x81, 0x46, 0x7e, 0xb8, 0x4f, + 0x56, 0x98, 0x90, 0xcf, 0x89, 0x05, 0xb7, 0x4c, 0xd3, 0xed, 0xa6, 0x3c, 0x53, 0x88, + 0xd5, 0x51, 0x5e, 0x3f, 0xd8, 0x1c, 0x70, 0xc1, 0x5e, 0x2a, 0x98, 0x2d, 0x59, 0x0e, + 0x87, 0xb8, 0x64, 0x45, 0x4b, 0xcd, 0xf5, 0xf8, 0x4d, 0x9f, 0x11, 0xcb, 0x9c, 0xf2, + 0xb5, 0xde, 0x3c, 0x5e, 0x0e, 0x2a, 0x6c, 0x48, 0x16, 0x61, 0x64, 0x96, 0x6f, 0xb9, + 0x0d, 0xac, 0xf8, 0x67, 0x4f, 0x9f, 0x1a, 0x34, 0xd2, 0xcd, 0xc7, 0xc9, 0x48, 0xab, + 0x99, 0xc3, 0x58, 0xa1, 0x95, 0x47, 0x0a, 0xdd, 0x06, 0x5e, 0xaf, 0x79, 0x24, 0xfa, + 0xed, 0x63, 0x27, 0xa6, 0x10, 0xf5, 0x2e, 0xd5, 0xd3, 0xa8, 0x7e, 0x11, 0xb5, 0x97, + 0x4f, 0xa0, 0x60, 0x45, 0xa4, 0x08, 0x95, 0xcd, 0xad, 0x60, 0x1c, 0xae, 0x01, 0xed, + 0xda, 0x17, 0x52, 0x81, 0x62, 0xd7, 0x21, 0x24, 0xf2, 0x05, 0x6b, 0x9a, 0xb8, 0xc0, + 0xc0, 0xf5, 0xc6, 0xdd, 0xaa, 0x0f, 0x5e, 0x33, 0xfb, 0x04, 0x23, 0x0b, 0x61, 0x1b, + 0xff, 0xd8, 0xbd, 0xdc, 0x63, 0x4c, 0x79, 0x60, 0xa3, 0xd4, 0xe6, 0x8f, 0x21, 0xe7, + 0x83, 0x04, 0xe4, 0xc4, 0xd2, 0xdc, 0xd6, 0xa1, 0x9c, 0xfc, 0x04, 0x57, 0x97, 0x09, + 0xf0, 0x33, 0xf1, 0x95, 0x78, 0xae, 0x7f, 0x0b, 0xc6, 0x46, 0x32, 0xa6, 0xd7, 0xda, + 0x40, 0xdc, 0x0c, 0x38, 0x1d, 0xd4, 0x49, 0xe1, 0xa0, 0xb0, 0xe7, 0xf8, 0xc5, 0xfe, + 0x88, 0xaa, 0x93, 0x4e, 0x16, 0xc8, 0xf1, 0xdb, 0xef, 0x72, 0x88, 0x34, 0xcf, 0x25, + 0x30, 0xe3, 0x3f, 0xb9, 0x27, 0xe9, 0x96, 0xce, 0x48, 0x89, 0xf9, 0xf6, 0xf4, 0x42, + 0x1c, 0x60, 0x78, 0xb0, 0x8d, 0x72, 0x2d, 0xc4, 0x4a, 0xb7, + ], + ock: [ + 0x67, 0x0e, 0xa5, 0x94, 0x8e, 0x85, 0x29, 0xa9, 0x52, 0xb2, 0x0a, 0xcc, 0x17, 0x70, + 0xe2, 0xa9, 0xc0, 0x67, 0xb0, 0x7b, 0x89, 0xfd, 0xaa, 0xf7, 0x84, 0xdf, 0x83, 0xfd, + 0x53, 0x7b, 0xdd, 0x86, + ], + op: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, + 0xa9, 0x19, 0xa2, 0x06, 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, + 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, + ], + c_out: [ + 0x20, 0xe0, 0x0c, 0xab, 0xc6, 0xc7, 0x06, 0xfa, 0x38, 0x19, 0x16, 0x78, 0x26, 0x44, + 0x90, 0x28, 0x9e, 0x0e, 0xd3, 0x2b, 0x9c, 0x77, 0x6d, 0xa2, 0xab, 0xe0, 0x21, 0x4f, + 0x89, 0x9b, 0xf9, 0x7b, 0x08, 0x3b, 0xe5, 0x8e, 0xdd, 0xbb, 0x57, 0x97, 0x28, 0x22, + 0xbb, 0x10, 0x8e, 0x2c, 0xad, 0xfc, 0x76, 0xab, 0xe6, 0x13, 0x13, 0x9e, 0x94, 0x1c, + 0x2c, 0xa1, 0x59, 0x21, 0x98, 0x91, 0xb1, 0x52, 0x83, 0xd8, 0x5a, 0x0d, 0xc9, 0x4d, + 0x59, 0xf9, 0x7b, 0x6c, 0x3c, 0x53, 0x6f, 0xcf, 0x93, 0x98, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x47, 0x30, 0x68, 0xbf, 0x68, 0xe5, 0x0b, 0xe3, 0x85, 0x7d, 0xec, 0xb2, 0xef, 0xd5, + 0xde, 0x20, 0xea, 0xc8, 0x1b, 0x37, 0x5b, 0xd0, 0xbb, 0xe8, 0x36, 0x86, 0x6e, 0x99, + 0x36, 0x3b, 0x37, 0x50, 0x9d, 0x53, 0x8f, 0xcc, 0xa9, 0x33, 0x37, 0xad, 0xbc, 0x24, + 0x81, 0xe2, 0x70, 0x26, 0x18, 0x4c, 0x3f, 0x4f, 0x48, 0xcc, 0x5d, 0x5a, 0x0e, 0x4a, + 0x4c, 0xfa, 0x4d, 0x6a, 0x24, 0x7f, 0x2e, 0x39, + ], + ovk: [ + 0x25, 0xb4, 0xc2, 0x6e, 0xb0, 0x3f, 0x71, 0x66, 0x46, 0x61, 0x9a, 0xf0, 0x24, 0x56, + 0xae, 0x69, 0x59, 0x62, 0xfe, 0x5e, 0x93, 0x1a, 0x63, 0xb5, 0xc7, 0x90, 0x52, 0xec, + 0xd3, 0x33, 0xe1, 0x84, + ], + default_d: [ + 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, + ], + default_pk_d: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, + ], + v: 15119422206032203650, + rseed: [ + 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, + 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, + 0x2d, 0x9b, 0x4c, 0x8f, + ], + asset: [ + 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, + 0x6a, 0xe8, 0xf7, 0xcc, 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, + 0x38, 0xe1, 0x73, 0x29, + ], + memo: [ + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, 0x02, 0xf3, 0xdc, 0xa1, 0x1c, 0x3b, 0x90, 0xcb, 0x21, 0x4e, + 0x68, 0xbc, 0x1c, 0xae, 0x03, 0x9d, 0x7a, 0x14, 0x6c, 0xdc, 0x1d, 0x60, 0x9d, 0x7a, + 0x6b, 0x3f, 0xd5, 0xd4, 0x61, 0xb0, 0x95, 0x1c, + ], + cv_net: [ + 0x45, 0x37, 0x85, 0x3e, 0x18, 0xac, 0x2c, 0xe9, 0x37, 0x79, 0x8c, 0x9b, 0xce, 0xa9, + 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, + 0x78, 0xe9, 0x97, 0x0b, + ], + nf_old: [ + 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, + 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, + 0x14, 0x7a, 0x27, 0x10, + ], + cmx: [ + 0x82, 0x9c, 0x4a, 0x9c, 0x2a, 0x01, 0x66, 0xc9, 0xba, 0x2e, 0x16, 0x9e, 0xdd, 0xda, + 0xe6, 0xdb, 0x59, 0xf0, 0x12, 0xa7, 0x26, 0x29, 0xce, 0x34, 0xf6, 0xc2, 0x88, 0x7e, + 0xfb, 0xe1, 0xd9, 0x3f, + ], + esk: [ + 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, 0x1d, 0xa4, 0xb1, 0x44, + 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, 0xaf, 0x2b, 0xd1, 0xa0, + 0x8c, 0x67, 0xd9, 0x3f, + ], + ephemeral_key: [ + 0x46, 0x73, 0x1f, 0xff, 0xc5, 0x9a, 0xf4, 0xc1, 0x28, 0x82, 0xbc, 0xca, 0xea, 0xa7, + 0xb8, 0xed, 0x39, 0x0b, 0x14, 0x66, 0x72, 0xe1, 0x36, 0x51, 0xc3, 0x2e, 0x57, 0x80, + 0x62, 0x68, 0x65, 0xa7, + ], + shared_secret: [ + 0x9d, 0x56, 0xbd, 0x96, 0x00, 0x39, 0x62, 0x5e, 0x11, 0x7d, 0x7b, 0xfe, 0xd4, 0x3a, + 0x57, 0x3b, 0x11, 0x51, 0x7f, 0xfa, 0x76, 0x14, 0xea, 0x2d, 0xa7, 0x7e, 0xdf, 0x62, + 0x7f, 0x6f, 0x13, 0xaa, + ], + k_enc: [ + 0x04, 0x2f, 0x92, 0x82, 0x13, 0x44, 0xde, 0x97, 0x7c, 0xee, 0x89, 0x9e, 0xd2, 0x1b, + 0xc8, 0x48, 0xf5, 0xc4, 0xfe, 0xdc, 0x39, 0xf2, 0xdf, 0xed, 0xad, 0x62, 0xcc, 0x7a, + 0x92, 0x7f, 0x74, 0xfd, + ], + p_enc: [ + 0x03, 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, 0x82, 0xcf, + 0xb3, 0xe7, 0x63, 0xfa, 0xd2, 0xd1, 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, + 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, + 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, 0x2d, 0x9b, 0x4c, 0x8f, 0x61, 0x16, 0xcf, 0xec, + 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, 0x6a, 0xe8, 0xf7, 0xcc, + 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, 0x38, 0xe1, 0x73, 0x29, + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, 0x02, 0xf3, 0xdc, 0xa1, 0x1c, 0x3b, 0x90, 0xcb, 0x21, 0x4e, + 0x68, 0xbc, 0x1c, 0xae, 0x03, 0x9d, 0x7a, 0x14, 0x6c, 0xdc, 0x1d, 0x60, 0x9d, 0x7a, + 0x6b, 0x3f, 0xd5, 0xd4, 0x61, 0xb0, 0x95, 0x1c, + ], + c_enc: [ + 0x16, 0x76, 0x72, 0x3a, 0x18, 0xff, 0x58, 0x77, 0x70, 0x15, 0x8d, 0x6b, 0x85, 0x09, + 0x3c, 0x49, 0x20, 0x16, 0xf8, 0x7e, 0xc3, 0xfa, 0xe8, 0xb0, 0xb4, 0x7c, 0xd9, 0x29, + 0x8f, 0xa2, 0x07, 0xc4, 0xb6, 0x09, 0xc6, 0x92, 0xdd, 0xb9, 0x10, 0x19, 0x72, 0xc9, + 0x4c, 0x71, 0x87, 0x84, 0x85, 0x42, 0x1e, 0xfb, 0x70, 0x1c, 0xf5, 0x15, 0xa2, 0x3f, + 0xbf, 0x36, 0xfe, 0x93, 0x54, 0x0d, 0x82, 0xd6, 0x9a, 0x72, 0x62, 0x4e, 0x25, 0x4f, + 0xe3, 0xa0, 0x11, 0xc5, 0xdb, 0xdb, 0xd2, 0xbd, 0xff, 0xb8, 0x83, 0x8a, 0xf3, 0x7d, + 0x03, 0xce, 0x69, 0x12, 0x6b, 0x2f, 0x68, 0x21, 0x25, 0xb7, 0xa9, 0xb2, 0xa3, 0xee, + 0x11, 0x8a, 0xe5, 0xad, 0xb4, 0x60, 0xa4, 0x68, 0x7c, 0x24, 0x30, 0x18, 0x7b, 0xfd, + 0x0f, 0x6c, 0x2a, 0x3d, 0x5d, 0x74, 0x30, 0x1c, 0xbd, 0x8f, 0xd0, 0x26, 0xc8, 0x64, + 0x4f, 0xbf, 0xa2, 0x65, 0x69, 0x88, 0xe9, 0x58, 0x59, 0x0b, 0x81, 0x6a, 0x1e, 0x64, + 0x0e, 0x46, 0x71, 0x0e, 0x46, 0xfa, 0x15, 0x94, 0xff, 0x2a, 0x61, 0xd6, 0xf6, 0xe7, + 0xb4, 0xa9, 0xf6, 0xe0, 0xde, 0x68, 0x3d, 0x95, 0xe5, 0x9d, 0x43, 0x57, 0xf7, 0x9a, + 0xc4, 0x93, 0x86, 0x6d, 0xab, 0x06, 0x57, 0x76, 0xc0, 0xb1, 0x43, 0x6b, 0x8e, 0x04, + 0x47, 0x68, 0x43, 0xc2, 0x8b, 0x48, 0x45, 0xea, 0xff, 0x17, 0x83, 0xa8, 0x50, 0xc2, + 0x4a, 0x90, 0x65, 0xc3, 0x36, 0x51, 0xc4, 0xb3, 0xdd, 0x19, 0x92, 0xf4, 0xf2, 0x08, + 0xb8, 0x51, 0xbf, 0xff, 0xe9, 0xb7, 0xbb, 0x7a, 0xad, 0x76, 0x7c, 0x23, 0x60, 0xb0, + 0x5c, 0x11, 0x23, 0x09, 0x66, 0xda, 0x55, 0x7e, 0x31, 0x3a, 0xe6, 0x1c, 0x95, 0x42, + 0x97, 0x66, 0x10, 0x6b, 0x4b, 0x1b, 0x35, 0x47, 0x64, 0xe4, 0xe1, 0xe4, 0xdf, 0x90, + 0xc1, 0x2d, 0x24, 0x37, 0x9d, 0x67, 0xba, 0xc6, 0x66, 0x97, 0xaf, 0x23, 0x44, 0x97, + 0xf2, 0xd6, 0xf9, 0xa6, 0x12, 0x85, 0x0d, 0xd7, 0x1d, 0x1c, 0x98, 0xce, 0x65, 0xd8, + 0x50, 0x7f, 0xa3, 0x46, 0x35, 0x83, 0x12, 0x39, 0xe2, 0x10, 0xf7, 0xdb, 0xb3, 0x05, + 0x04, 0x2d, 0x47, 0x50, 0xd9, 0x5a, 0xdf, 0xff, 0xc9, 0x8d, 0xeb, 0x0f, 0x17, 0x13, + 0xbc, 0x01, 0xaf, 0x5d, 0xb5, 0x99, 0x29, 0x89, 0x76, 0xab, 0xba, 0xdb, 0x0f, 0x4d, + 0xed, 0x1a, 0x2f, 0xe4, 0xcf, 0x90, 0x60, 0x0e, 0x0d, 0x28, 0xd3, 0x07, 0xc6, 0x41, + 0xf7, 0x52, 0x3c, 0x16, 0x66, 0x40, 0x1d, 0x78, 0x6f, 0xd2, 0x4a, 0xe1, 0x68, 0x0f, + 0xe9, 0x26, 0x70, 0x4c, 0xb6, 0xe2, 0xaf, 0x80, 0x1a, 0x0d, 0x82, 0x75, 0x9d, 0xd8, + 0x7a, 0x8c, 0xd8, 0x7b, 0x85, 0xbb, 0x07, 0x51, 0xa7, 0x08, 0xc9, 0xf4, 0xa7, 0xd3, + 0x24, 0xe5, 0xc9, 0x3a, 0xd2, 0x2b, 0x86, 0x43, 0xdf, 0xfa, 0x5f, 0x50, 0x79, 0xfc, + 0x6f, 0x01, 0x6d, 0x94, 0x3c, 0x99, 0x09, 0x27, 0x5c, 0x96, 0xf5, 0xfe, 0x7b, 0x56, + 0x33, 0x3c, 0x24, 0x01, 0x99, 0x73, 0xd9, 0x4f, 0x06, 0xeb, 0xf6, 0xc0, 0xf6, 0xef, + 0xdd, 0x42, 0xea, 0xb0, 0x63, 0x49, 0xd5, 0xe8, 0xb9, 0x60, 0xba, 0x8c, 0x68, 0xee, + 0xfd, 0x44, 0x49, 0x99, 0xf6, 0xfa, 0x3d, 0x6a, 0x3a, 0xe3, 0x1a, 0xe8, 0x54, 0x6e, + 0xdc, 0x62, 0x78, 0x25, 0x63, 0x7e, 0x1e, 0x86, 0x39, 0x8d, 0x0e, 0xd3, 0xd8, 0x8b, + 0xfa, 0xea, 0x8b, 0x4b, 0x08, 0x50, 0xd8, 0xa8, 0x28, 0x6e, 0xa9, 0xf3, 0xd1, 0x3f, + 0xa8, 0xf4, 0x16, 0x53, 0x45, 0x1b, 0x97, 0xb3, 0x8b, 0x06, 0x3a, 0x5f, 0xc6, 0xdb, + 0xe4, 0xe9, 0x19, 0x94, 0x87, 0xc9, 0x73, 0xef, 0x8f, 0x2c, 0x26, 0x3f, 0x85, 0x05, + 0xf4, 0xc3, 0xbe, 0xc9, 0xd1, 0x79, 0xbb, 0xd6, 0x5d, 0x1e, 0xdc, 0x58, 0x95, 0xa1, + 0x6c, 0xc7, 0x98, 0x6b, 0xcf, 0xc4, 0xba, 0xe8, 0x7e, 0xc0, 0xb2, 0x9b, 0xf1, 0xb3, + 0x97, 0x61, 0x5c, 0x95, 0x13, 0xfa, 0x52, 0xeb, 0xe1, 0xe9, 0xfc, 0xfb, 0xf1, 0x92, + 0xed, 0x49, 0x26, 0x27, 0x27, 0xa0, 0x8a, 0xd3, 0xc2, 0x95, 0x5b, 0x3d, 0xf2, 0xee, + 0xad, 0x30, 0x24, 0x3e, 0x32, 0xb2, 0x54, 0x1e, 0x8f, 0x9f, 0xce, 0x6c, 0xa5, 0xe7, + 0x0f, 0xf3, 0xa5, 0xe9, 0x35, 0x2b, 0xb8, 0x93, 0xe3, 0xdc, 0xa2, 0x74, 0xa1, 0x11, + 0xbb, 0xd6, 0x9c, 0x2b, 0x4c, 0x2e, 0xc9, 0x49, 0x81, 0x3d, 0xb7, 0x8c, 0x5e, 0x16, + 0xbc, 0x7a, 0xf6, 0x72, 0xb2, 0x0d, 0x7a, 0x16, 0xec, 0x48, + ], + ock: [ + 0xa8, 0xa5, 0x77, 0x53, 0x40, 0x60, 0x3d, 0xad, 0x7d, 0x52, 0x3c, 0x94, 0x64, 0x4b, + 0x4d, 0x3f, 0x61, 0x92, 0xfb, 0x19, 0x8e, 0x8d, 0xe5, 0x70, 0x61, 0x52, 0xf4, 0x55, + 0x68, 0x24, 0x58, 0x73, + ], + op: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, + 0x1d, 0xa4, 0xb1, 0x44, 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, + 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, + ], + c_out: [ + 0xe3, 0x49, 0x59, 0x73, 0x78, 0x12, 0xaf, 0x29, 0xef, 0x95, 0x78, 0x3d, 0xcf, 0xb2, + 0xfd, 0x19, 0xab, 0x10, 0xd2, 0x17, 0xdd, 0x7d, 0x7f, 0xa6, 0x9e, 0x45, 0x21, 0xfe, + 0x8e, 0xce, 0x1a, 0x86, 0xee, 0x5b, 0xaf, 0x9d, 0xe8, 0x51, 0x2f, 0x84, 0xa2, 0xb9, + 0x12, 0xbf, 0xa3, 0x2e, 0x50, 0xc9, 0x1e, 0xfc, 0xfa, 0x14, 0x50, 0xb7, 0xdb, 0x82, + 0xd5, 0xa2, 0xa9, 0x9d, 0x40, 0xf7, 0xbd, 0x6d, 0x66, 0xd5, 0xaa, 0x9a, 0x13, 0xec, + 0xc1, 0x61, 0x05, 0x74, 0x0a, 0x68, 0xdb, 0xd9, 0x5e, 0x0a, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xfc, 0x8c, 0x64, 0x1c, 0x0b, 0x28, 0xbe, 0xbf, 0x85, 0x24, 0x25, 0xae, 0x95, 0x5f, + 0xe6, 0x40, 0x1c, 0xfd, 0x9e, 0x60, 0x63, 0xf2, 0x50, 0x11, 0x3d, 0xa0, 0xb5, 0x8b, + 0x2a, 0x0f, 0x49, 0xb9, 0x12, 0x0b, 0x89, 0x9f, 0x08, 0x10, 0x6b, 0x30, 0x86, 0xb2, + 0xf4, 0x11, 0x63, 0x6f, 0x50, 0xab, 0x48, 0x7c, 0xfb, 0x28, 0x81, 0x89, 0x77, 0x8f, + 0xe4, 0xe5, 0xa1, 0x91, 0x8b, 0x98, 0xd5, 0x0a, + ], + ovk: [ + 0xbe, 0xd1, 0x7d, 0xf5, 0xf8, 0x88, 0xc8, 0xca, 0x14, 0x67, 0xae, 0x17, 0xdb, 0xbc, + 0xde, 0x31, 0xc1, 0x10, 0x5c, 0xb5, 0xbd, 0xa8, 0x8a, 0xc6, 0xc6, 0x27, 0x00, 0x2c, + 0xe2, 0x1c, 0x02, 0x14, + ], + default_d: [ + 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, + ], + default_pk_d: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, + ], + v: 7555450289479839818, + rseed: [ + 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, + 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, + 0x03, 0xaa, 0xe0, 0x4b, + ], + asset: [ + 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, + 0x62, 0xcd, 0x1c, 0xa0, 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, + 0x82, 0x1a, 0x41, 0x84, + ], + memo: [ + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, 0xa5, 0x4d, 0xcf, 0xbf, 0x2b, 0x9c, 0x49, 0xd1, 0x42, 0x06, + 0x42, 0x09, 0xee, 0xee, 0xd4, 0xd4, 0x71, 0xff, 0xc0, 0x17, 0xd4, 0xe2, 0x0a, 0x79, + 0x6b, 0x09, 0x27, 0x80, 0x4c, 0x06, 0x1b, 0x9f, + ], + cv_net: [ + 0x71, 0x00, 0xa7, 0x52, 0x93, 0xf4, 0xae, 0xfd, 0x89, 0xa1, 0x66, 0xa5, 0xf8, 0x4d, + 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, + 0x68, 0x2d, 0xc2, 0xab, + ], + nf_old: [ + 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, + 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, + 0xb9, 0xd0, 0xb7, 0x32, + ], + cmx: [ + 0xde, 0x71, 0x70, 0xc9, 0xd8, 0x0f, 0x64, 0x00, 0x29, 0x73, 0xc2, 0xc7, 0x58, 0x02, + 0x7b, 0xc4, 0x38, 0xe5, 0x83, 0x68, 0x56, 0xa7, 0x40, 0x03, 0x20, 0xb1, 0xbd, 0xe2, + 0xed, 0xa1, 0x7d, 0x31, + ], + esk: [ + 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, 0x58, 0x93, 0x20, 0x26, + 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, 0x44, 0x72, 0x83, 0xf9, + 0x4e, 0xd5, 0x95, 0x3d, + ], + ephemeral_key: [ + 0xce, 0x67, 0x94, 0x31, 0x5f, 0x46, 0x2d, 0xed, 0xf3, 0xc5, 0x77, 0x4a, 0xac, 0x7f, + 0x3c, 0x7b, 0x70, 0xba, 0x7d, 0x72, 0x43, 0xbb, 0x0c, 0xc3, 0xb0, 0x67, 0xdc, 0x28, + 0x38, 0xf1, 0x11, 0xa3, + ], + shared_secret: [ + 0xea, 0x22, 0x6b, 0x69, 0xec, 0x2d, 0x9f, 0xcf, 0x91, 0x9c, 0xe5, 0x70, 0x06, 0x09, + 0x89, 0x94, 0xf7, 0x14, 0xb3, 0x9c, 0x34, 0x61, 0x52, 0xbc, 0x11, 0x51, 0xa0, 0xc6, + 0x9e, 0xe0, 0x04, 0x06, + ], + k_enc: [ + 0xb4, 0x56, 0x1b, 0xdb, 0xe0, 0xea, 0x44, 0x20, 0x75, 0xe7, 0xe6, 0x6f, 0xb3, 0xc0, + 0xfa, 0xd3, 0xaf, 0xc2, 0x85, 0x6e, 0xf4, 0xf3, 0x61, 0xb4, 0xac, 0x33, 0xaa, 0xe0, + 0x15, 0x52, 0xfd, 0x49, + ], + p_enc: [ + 0x03, 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, 0x4a, 0x70, + 0x91, 0xfe, 0x01, 0x5a, 0xda, 0x68, 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, + 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, + 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, 0x03, 0xaa, 0xe0, 0x4b, 0x29, 0x8a, 0xc0, 0xaf, + 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, 0x62, 0xcd, 0x1c, 0xa0, + 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, 0x82, 0x1a, 0x41, 0x84, + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, 0xa5, 0x4d, 0xcf, 0xbf, 0x2b, 0x9c, 0x49, 0xd1, 0x42, 0x06, + 0x42, 0x09, 0xee, 0xee, 0xd4, 0xd4, 0x71, 0xff, 0xc0, 0x17, 0xd4, 0xe2, 0x0a, 0x79, + 0x6b, 0x09, 0x27, 0x80, 0x4c, 0x06, 0x1b, 0x9f, + ], + c_enc: [ + 0x59, 0x9a, 0x4d, 0x9f, 0x53, 0x3c, 0x46, 0xa9, 0x6f, 0x92, 0xaf, 0x8c, 0x08, 0xae, + 0x59, 0x71, 0x10, 0x23, 0x0e, 0xb8, 0x41, 0xc2, 0xf7, 0xc9, 0xd4, 0xf1, 0x45, 0x87, + 0x76, 0x36, 0xc8, 0x9d, 0xd8, 0xf3, 0x84, 0xa9, 0x40, 0xdc, 0x89, 0x72, 0x55, 0x53, + 0x57, 0xbc, 0x07, 0x48, 0x2a, 0x0a, 0x32, 0x3d, 0x87, 0xae, 0x10, 0xeb, 0x99, 0x82, + 0x5a, 0xe4, 0xe0, 0x06, 0x0e, 0x25, 0x6c, 0x3c, 0x3b, 0xeb, 0xa3, 0x2f, 0xa2, 0xb2, + 0xd2, 0x7f, 0x04, 0x6f, 0x7a, 0x93, 0x6d, 0xf8, 0xa9, 0x61, 0xc8, 0x18, 0x4e, 0xe3, + 0xc6, 0x8e, 0xbc, 0xe9, 0x80, 0x64, 0x45, 0xb4, 0x3e, 0x66, 0x67, 0x19, 0x95, 0xa2, + 0x43, 0x7a, 0x7f, 0x70, 0x91, 0x47, 0x14, 0x8a, 0x76, 0x03, 0x6d, 0x25, 0x5e, 0xba, + 0xc4, 0xd0, 0xd8, 0x34, 0x82, 0x93, 0x23, 0x9a, 0x78, 0x64, 0xe7, 0x9b, 0xef, 0xf7, + 0x6f, 0x61, 0x50, 0xe0, 0xc4, 0xf4, 0x7a, 0x85, 0x26, 0xe3, 0xed, 0x06, 0x75, 0xfa, + 0xc6, 0xac, 0xcc, 0x30, 0xa4, 0xd6, 0x73, 0xca, 0x80, 0x85, 0x95, 0x96, 0xfe, 0xc9, + 0xcd, 0x6a, 0x93, 0xfb, 0xa0, 0xe8, 0x9e, 0xf5, 0x3f, 0x3e, 0x26, 0x74, 0xd3, 0x2a, + 0x4b, 0x43, 0xf9, 0xa4, 0x38, 0x7d, 0xce, 0x33, 0xac, 0xa1, 0xe4, 0xff, 0xdc, 0x6d, + 0x2d, 0x31, 0x89, 0xc6, 0x23, 0xca, 0x56, 0x4d, 0x03, 0xac, 0x5b, 0x35, 0xb1, 0xa7, + 0x47, 0xff, 0x44, 0x6b, 0xc2, 0x5e, 0xd2, 0x2d, 0x09, 0x68, 0x2c, 0xef, 0x3a, 0x30, + 0xff, 0xa5, 0xc4, 0x0e, 0x27, 0x70, 0xf1, 0x84, 0x98, 0xb1, 0x2f, 0x86, 0x8b, 0xa9, + 0x2a, 0x13, 0xaa, 0x4f, 0xa2, 0x14, 0xb0, 0x62, 0xe3, 0x64, 0x9c, 0xf9, 0xc8, 0x5e, + 0x7a, 0x8a, 0x55, 0xf5, 0xf3, 0xdd, 0x68, 0x84, 0x2a, 0xea, 0x7c, 0x92, 0x79, 0x2a, + 0x52, 0x60, 0x0f, 0x86, 0x6c, 0x34, 0xa1, 0x0c, 0x51, 0x14, 0x13, 0x62, 0x02, 0x24, + 0xfb, 0x85, 0xaf, 0xc6, 0x06, 0xdd, 0x4f, 0x7b, 0x2f, 0x76, 0xbe, 0x76, 0x0c, 0xa1, + 0x94, 0xb6, 0xd4, 0x88, 0x2e, 0x5a, 0x4a, 0x76, 0x3d, 0x75, 0x0d, 0xb7, 0xe1, 0x68, + 0xa4, 0x18, 0x11, 0x92, 0x35, 0xda, 0xf9, 0xcb, 0x1b, 0xdb, 0x07, 0xff, 0x46, 0x83, + 0x3a, 0x87, 0xa3, 0x92, 0x6b, 0x14, 0xa5, 0x26, 0x4f, 0x10, 0x4f, 0x7f, 0x89, 0xf7, + 0x6f, 0x10, 0x10, 0x8f, 0x2b, 0x6e, 0xa5, 0x05, 0xd4, 0xf0, 0xd2, 0x6d, 0x58, 0x31, + 0x1c, 0xc7, 0x21, 0x9c, 0x6b, 0xc4, 0x38, 0xd0, 0xe1, 0xb3, 0x17, 0x60, 0x18, 0x73, + 0x9e, 0x6f, 0x75, 0xd0, 0x73, 0x59, 0xf5, 0xe8, 0x95, 0x7e, 0x12, 0xc3, 0x03, 0xaa, + 0x52, 0x9b, 0x11, 0xa1, 0x81, 0x66, 0x25, 0xa1, 0x20, 0xf3, 0x6d, 0xcd, 0xdd, 0xff, + 0x9c, 0x65, 0xbc, 0xac, 0x8f, 0x10, 0x67, 0xc7, 0xfe, 0x88, 0xf6, 0x44, 0x85, 0x94, + 0xcf, 0x1d, 0xff, 0x8e, 0x29, 0x00, 0xae, 0x84, 0xd2, 0xa7, 0xc8, 0x1b, 0x90, 0x6d, + 0xd0, 0xbc, 0x86, 0x96, 0xe3, 0x70, 0x98, 0x07, 0x4b, 0x75, 0xd8, 0x38, 0xd8, 0xab, + 0xdc, 0x90, 0x46, 0x08, 0x2b, 0xe4, 0xa6, 0x09, 0x95, 0xc4, 0xf4, 0xed, 0x80, 0xe2, + 0xd7, 0x87, 0x38, 0x25, 0x77, 0x3b, 0xa6, 0x3e, 0xe4, 0xcb, 0x97, 0x36, 0x9a, 0x50, + 0x70, 0xb5, 0x72, 0x5c, 0x5f, 0xeb, 0x32, 0x62, 0x45, 0x87, 0x80, 0x1e, 0x5a, 0xc0, + 0x30, 0xe6, 0x45, 0xbd, 0xf2, 0xe5, 0x86, 0xcf, 0x98, 0x66, 0xea, 0xfb, 0x76, 0xf5, + 0x59, 0x76, 0xa3, 0x3d, 0x62, 0xae, 0xdc, 0x76, 0x27, 0x78, 0x3b, 0x48, 0x48, 0x93, + 0x61, 0xf9, 0x9c, 0xae, 0xb1, 0xb1, 0x9c, 0x55, 0x22, 0x58, 0x9f, 0xd2, 0x1d, 0x51, + 0x45, 0x49, 0xd7, 0x4a, 0xb1, 0x92, 0x25, 0xed, 0x6e, 0x4c, 0x20, 0x3a, 0xdd, 0xfa, + 0x55, 0xfc, 0x9e, 0xc9, 0x89, 0xb6, 0x69, 0x02, 0x3c, 0xf3, 0x05, 0xb4, 0x2b, 0x33, + 0x0f, 0xc2, 0x30, 0x80, 0xab, 0xe4, 0x25, 0x01, 0xe5, 0x9c, 0x85, 0x1c, 0x54, 0xc7, + 0x49, 0x66, 0xf6, 0x0b, 0xe9, 0xdc, 0x56, 0x1a, 0x2d, 0x91, 0xf5, 0xd3, 0x2a, 0xdd, + 0x19, 0xb8, 0x9a, 0xca, 0xbe, 0x92, 0x1b, 0x99, 0x25, 0x3a, 0xfe, 0xfb, 0x2f, 0xf6, + 0x42, 0xd8, 0x6e, 0x65, 0x59, 0x51, 0x95, 0x8e, 0xfb, 0x82, 0xab, 0xe5, 0x84, 0x5d, + 0xad, 0xf0, 0x13, 0x27, 0x03, 0x7e, 0xda, 0x01, 0xf9, 0x97, 0xd4, 0x19, 0x4f, 0x97, + 0xb7, 0xd7, 0xef, 0xa4, 0xf4, 0xd0, 0x18, 0x2d, 0xa4, 0xc4, + ], + ock: [ + 0x9d, 0x33, 0x8d, 0x19, 0x91, 0xba, 0x13, 0xfe, 0xe7, 0x37, 0x70, 0x9b, 0x7a, 0xbb, + 0x50, 0x77, 0x8d, 0xe1, 0xd8, 0x2f, 0xdb, 0x6b, 0x34, 0x7f, 0x58, 0xdd, 0xf5, 0x78, + 0xdd, 0x54, 0x42, 0xd7, + ], + op: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, + 0x58, 0x93, 0x20, 0x26, 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, + 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, + ], + c_out: [ + 0x1f, 0x61, 0xfa, 0x64, 0x74, 0xce, 0xd5, 0x5b, 0xcf, 0xc9, 0x40, 0x5f, 0x9b, 0x07, + 0xc6, 0x02, 0xb9, 0x71, 0x4b, 0xf4, 0x02, 0x1d, 0x59, 0x4d, 0x72, 0xcf, 0xc6, 0x46, + 0x13, 0xd9, 0x01, 0x0c, 0x92, 0x4a, 0x7a, 0xc6, 0x74, 0x5d, 0x04, 0x8b, 0x15, 0xcc, + 0x94, 0xc4, 0x86, 0x4d, 0x1e, 0x0b, 0x4b, 0x43, 0x55, 0xac, 0x8e, 0xbb, 0x40, 0xee, + 0x36, 0x14, 0x00, 0x11, 0xf4, 0xc0, 0x1b, 0x3f, 0x53, 0xc0, 0xf6, 0x3a, 0xb5, 0x64, + 0x74, 0x81, 0x27, 0x73, 0x0e, 0x6c, 0x58, 0x4a, 0xf9, 0xb3, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x53, 0x3d, 0xc3, 0xd4, 0x93, 0xf2, 0xb8, 0x7a, 0x03, 0x3d, 0xf5, 0x07, 0x05, 0xf2, + 0x90, 0x54, 0x16, 0x38, 0xe9, 0x08, 0x7d, 0xcd, 0xbc, 0xfe, 0x52, 0x7e, 0x77, 0x5a, + 0xaf, 0x09, 0x30, 0x29, 0xac, 0xec, 0x74, 0xdd, 0xe6, 0x02, 0xfc, 0x7c, 0x73, 0xcb, + 0x38, 0x50, 0xbd, 0xfb, 0xf2, 0x61, 0x79, 0x4c, 0x9c, 0x29, 0x9d, 0x0b, 0x98, 0xee, + 0x0f, 0x20, 0x71, 0xd6, 0xd4, 0xe3, 0x7b, 0x05, + ], + ovk: [ + 0x32, 0x4d, 0xce, 0x2a, 0x1e, 0xa1, 0xe4, 0x30, 0x4f, 0x49, 0xe4, 0x3a, 0xe0, 0x65, + 0xe3, 0xfb, 0x19, 0x6f, 0x76, 0xd9, 0xb8, 0x79, 0xc7, 0x20, 0x08, 0x62, 0xea, 0xd1, + 0x8d, 0xea, 0x5f, 0xb6, + ], + default_d: [ + 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, + ], + default_pk_d: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, + ], + v: 12711846894898776584, + rseed: [ + 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, + 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, + 0xad, 0xe8, 0x24, 0xf3, + ], + asset: [ + 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, + 0xf1, 0xb1, 0xaa, 0x9b, 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, + 0xe3, 0x81, 0x93, 0xbc, + ], + memo: [ + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, 0x78, 0xf4, 0xfb, 0x11, 0x12, 0xf4, 0x02, 0x8a, 0x70, 0x4f, + 0xc5, 0xa9, 0x38, 0x2c, 0x6b, 0x03, 0xe7, 0xd8, 0x08, 0x5e, 0x90, 0x6c, 0xf8, 0x4c, + 0xa2, 0xc1, 0x20, 0x7c, 0x87, 0xa2, 0xbc, 0xe2, + ], + cv_net: [ + 0x5d, 0xd1, 0x3d, 0xcf, 0x9a, 0xf3, 0x52, 0xf5, 0xfe, 0x0b, 0x2b, 0xcb, 0xd0, 0xdb, + 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, + 0xbe, 0x4b, 0x4f, 0x87, + ], + nf_old: [ + 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, + 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, + 0x41, 0x84, 0x28, 0x2a, + ], + cmx: [ + 0x1e, 0xaa, 0x25, 0x97, 0xb0, 0x8f, 0x7c, 0x9c, 0x57, 0x9c, 0xe1, 0x43, 0xb7, 0xfb, + 0x2b, 0x10, 0x33, 0x82, 0xff, 0x63, 0x77, 0xb1, 0xc8, 0xbf, 0xbc, 0xcd, 0x8d, 0xa2, + 0x97, 0xe0, 0xa9, 0x0c, + ], + esk: [ + 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, 0xdf, 0x7c, 0xe2, 0xd2, + 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, 0x86, 0x48, 0x56, 0x2c, + 0xbd, 0x86, 0x3f, 0x09, + ], + ephemeral_key: [ + 0x5a, 0x48, 0x58, 0x15, 0xc4, 0xa7, 0x47, 0x06, 0xe9, 0xde, 0x87, 0xfa, 0x60, 0xa2, + 0x81, 0x6f, 0x89, 0x0b, 0xe3, 0xdb, 0x54, 0xeb, 0x3f, 0x4b, 0xaf, 0x37, 0xdb, 0xc9, + 0xbd, 0xe5, 0xfe, 0x9d, + ], + shared_secret: [ + 0x96, 0x8d, 0xf2, 0xe8, 0x5d, 0x7b, 0xd1, 0x08, 0xf5, 0x72, 0x12, 0x53, 0x93, 0x76, + 0xaf, 0x25, 0x83, 0x2e, 0xf4, 0xdb, 0xd6, 0x40, 0x2a, 0x41, 0x4d, 0x73, 0xc5, 0x6b, + 0xee, 0xe4, 0xf2, 0xa8, + ], + k_enc: [ + 0xf7, 0x73, 0x91, 0x24, 0x3f, 0xdb, 0x35, 0xb2, 0x26, 0x94, 0xdb, 0x91, 0xde, 0xbd, + 0x78, 0x55, 0x79, 0x3c, 0xa7, 0x1e, 0x82, 0xbd, 0xc2, 0xee, 0x74, 0xc9, 0xb7, 0xb6, + 0x97, 0xc0, 0x24, 0x71, + ], + p_enc: [ + 0x03, 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, 0x08, 0x0a, + 0x98, 0x91, 0x66, 0x8d, 0x69, 0xb0, 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, + 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, + 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, 0xad, 0xe8, 0x24, 0xf3, 0xf9, 0x78, 0x1e, 0xbe, + 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, 0xf1, 0xb1, 0xaa, 0x9b, + 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, 0xe3, 0x81, 0x93, 0xbc, + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, 0x78, 0xf4, 0xfb, 0x11, 0x12, 0xf4, 0x02, 0x8a, 0x70, 0x4f, + 0xc5, 0xa9, 0x38, 0x2c, 0x6b, 0x03, 0xe7, 0xd8, 0x08, 0x5e, 0x90, 0x6c, 0xf8, 0x4c, + 0xa2, 0xc1, 0x20, 0x7c, 0x87, 0xa2, 0xbc, 0xe2, + ], + c_enc: [ + 0xf9, 0x09, 0x97, 0x73, 0x8b, 0x14, 0xd8, 0xa8, 0x4e, 0x32, 0x74, 0xbb, 0x70, 0x76, + 0x31, 0x15, 0xb7, 0x2e, 0x0a, 0x3d, 0xde, 0x8e, 0xa4, 0x70, 0x91, 0x1f, 0xb4, 0x58, + 0x70, 0xb0, 0x14, 0x8e, 0x7d, 0x37, 0x2b, 0xf2, 0x26, 0x8b, 0x3e, 0xe8, 0xda, 0xe5, + 0xfd, 0xe5, 0xea, 0x9b, 0x61, 0x59, 0x8e, 0xf1, 0x1b, 0x73, 0x14, 0x4f, 0x75, 0x53, + 0xb2, 0x13, 0xa0, 0x4c, 0x85, 0xf2, 0x5c, 0x54, 0x6c, 0x8a, 0x38, 0xa6, 0x0e, 0x50, + 0x86, 0x08, 0xb9, 0xca, 0x59, 0x3b, 0x94, 0xd8, 0x68, 0x8d, 0x6e, 0xff, 0xa5, 0x36, + 0x04, 0xd4, 0xdb, 0xc0, 0xf3, 0x45, 0x03, 0xaa, 0xe4, 0x6f, 0x3c, 0x8a, 0x8d, 0x2e, + 0x46, 0xa8, 0x1f, 0x09, 0x12, 0x6c, 0x45, 0x36, 0xfd, 0x02, 0x58, 0xf5, 0x97, 0x40, + 0xad, 0x0d, 0xb8, 0x02, 0xcc, 0x02, 0x42, 0x53, 0x4d, 0xdf, 0x52, 0xa6, 0xbf, 0x6a, + 0x03, 0x4d, 0xe6, 0x26, 0xf0, 0x18, 0x84, 0x4a, 0xdc, 0xb2, 0x6d, 0xcd, 0xc2, 0x85, + 0x16, 0x37, 0x16, 0xdd, 0x54, 0x65, 0x1c, 0x88, 0x73, 0x53, 0xf1, 0xff, 0xef, 0xa0, + 0x37, 0x71, 0x2a, 0xc0, 0xdf, 0x3a, 0x92, 0x98, 0x19, 0x06, 0x87, 0x54, 0x9d, 0x79, + 0xc6, 0xa3, 0x60, 0x0c, 0xc1, 0xc7, 0x29, 0xa3, 0x93, 0xd4, 0x4f, 0xec, 0xe5, 0x7f, + 0xd4, 0xcb, 0x0c, 0x0f, 0xb0, 0xc7, 0x86, 0x1b, 0x92, 0x5b, 0x94, 0xcd, 0x6a, 0x26, + 0x90, 0xf0, 0x02, 0xc4, 0x3a, 0x16, 0x6e, 0x56, 0x77, 0x72, 0x9f, 0x35, 0x52, 0xae, + 0xe0, 0xf2, 0xc1, 0x95, 0xaa, 0x91, 0xb2, 0xdd, 0xe3, 0x65, 0xdd, 0x14, 0xf2, 0xf0, + 0x7b, 0x3c, 0x38, 0x34, 0x7f, 0x6c, 0x0d, 0xab, 0x82, 0x84, 0x1e, 0xba, 0xde, 0x1e, + 0xf8, 0x13, 0xf2, 0xcd, 0x88, 0x5b, 0x57, 0x84, 0x37, 0x44, 0x45, 0x24, 0x93, 0x6a, + 0x65, 0x46, 0xc4, 0x55, 0xd6, 0xc9, 0x2e, 0x6d, 0x3d, 0xc5, 0x38, 0xb6, 0xcd, 0x9f, + 0x6d, 0x4c, 0xc0, 0xd7, 0x4d, 0x7b, 0xc2, 0x46, 0x7e, 0x21, 0x5b, 0xe8, 0xc3, 0xd4, + 0xff, 0x91, 0x8a, 0x2d, 0x98, 0x71, 0x00, 0xff, 0x34, 0x02, 0x4c, 0x88, 0x62, 0x79, + 0xd6, 0x4c, 0xaf, 0xdf, 0xd9, 0x0f, 0x1c, 0x04, 0xc4, 0x6b, 0xc9, 0xd5, 0xe9, 0xe2, + 0xaf, 0xd0, 0x3a, 0xb7, 0x55, 0xe4, 0x0f, 0x08, 0x7e, 0xb5, 0x1e, 0xe3, 0xd1, 0x02, + 0xb6, 0xb0, 0x69, 0xb6, 0x50, 0xf5, 0xd8, 0x55, 0x03, 0x35, 0x47, 0x1b, 0x24, 0x46, + 0x5d, 0x93, 0x4d, 0x63, 0x34, 0x39, 0xb1, 0x08, 0xd9, 0x04, 0x2b, 0x37, 0xf9, 0xf7, + 0x2e, 0x74, 0xfd, 0x6b, 0xa0, 0x01, 0x58, 0x5b, 0x08, 0x62, 0xdb, 0x99, 0x4a, 0x5e, + 0xc1, 0x2d, 0xc9, 0x1e, 0x01, 0x48, 0x6a, 0x8d, 0xc6, 0x8a, 0xb9, 0xa3, 0x41, 0x93, + 0x52, 0x61, 0x73, 0xec, 0xc0, 0xd1, 0x55, 0xb5, 0xcd, 0xd6, 0xbc, 0x07, 0xe6, 0x3e, + 0x41, 0xaf, 0x9e, 0x52, 0x4c, 0xd3, 0xe6, 0x55, 0x5d, 0x38, 0xb4, 0x6d, 0xb2, 0xd9, + 0x9e, 0x5b, 0xa4, 0xa4, 0x95, 0xff, 0x30, 0xfe, 0xf2, 0x54, 0xc9, 0xfe, 0x7b, 0x79, + 0x0c, 0xe5, 0x6a, 0x40, 0xf4, 0x00, 0x27, 0xbb, 0x62, 0x05, 0x86, 0x38, 0xc4, 0x94, + 0x17, 0x7b, 0x7f, 0x5c, 0x8f, 0x29, 0x44, 0x9e, 0x9e, 0xc3, 0xbd, 0xb3, 0xab, 0x04, + 0x16, 0x0d, 0x96, 0xd0, 0xd4, 0x04, 0x79, 0x5d, 0x54, 0x28, 0x40, 0x82, 0xb6, 0x35, + 0x7d, 0x58, 0x1d, 0xc2, 0x64, 0x81, 0x13, 0x67, 0xbb, 0xb1, 0x31, 0x9a, 0x31, 0xf7, + 0x66, 0x4a, 0x4e, 0xca, 0x93, 0x2a, 0xbb, 0xd7, 0x33, 0xa7, 0x1a, 0x31, 0xaf, 0x23, + 0x11, 0xc4, 0x9a, 0xc9, 0xaf, 0x22, 0xf8, 0x16, 0x7b, 0x25, 0x51, 0xac, 0xf5, 0x73, + 0xd9, 0x1b, 0x40, 0x98, 0xc4, 0xde, 0xa8, 0xa9, 0x79, 0x9d, 0x9d, 0x54, 0x52, 0x0c, + 0xc6, 0x3e, 0x55, 0x71, 0x8a, 0x24, 0x85, 0xbf, 0x6f, 0x63, 0x16, 0x30, 0x7c, 0xea, + 0x21, 0x5e, 0x22, 0x22, 0x8d, 0x45, 0x34, 0x9a, 0x03, 0x50, 0x31, 0xa4, 0xcb, 0x67, + 0x7b, 0x52, 0x3a, 0x3a, 0x51, 0x25, 0x2c, 0x6c, 0x61, 0xd0, 0xe2, 0x43, 0x2b, 0x94, + 0xac, 0x9c, 0x0d, 0xb5, 0x0d, 0xbc, 0xb9, 0xa2, 0xaf, 0x76, 0xb9, 0xf9, 0x11, 0x0a, + 0xd6, 0xcc, 0x2e, 0x7d, 0xe6, 0x49, 0x3a, 0x8e, 0x3c, 0xd1, 0xab, 0xf0, 0x6f, 0x4a, + 0x2d, 0x47, 0x5e, 0xc7, 0x60, 0xeb, 0x7c, 0x36, 0xbb, 0xb1, 0x27, 0x50, 0x61, 0x10, + 0x2d, 0xb3, 0x35, 0x6e, 0x11, 0x4d, 0xbc, 0xa3, 0xc5, 0xd8, + ], + ock: [ + 0x3c, 0x85, 0x16, 0x2e, 0x48, 0x67, 0xfc, 0x45, 0x89, 0xf6, 0xc6, 0x07, 0x69, 0x3b, + 0x8f, 0x4a, 0x7e, 0x85, 0xe0, 0x19, 0xf2, 0x33, 0x2f, 0xeb, 0xff, 0x08, 0xcb, 0xad, + 0x99, 0x4b, 0x3e, 0x81, + ], + op: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, + 0xdf, 0x7c, 0xe2, 0xd2, 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, + 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, + ], + c_out: [ + 0x92, 0x05, 0x27, 0xe0, 0x4a, 0xa5, 0x39, 0xdd, 0x95, 0x62, 0x23, 0x36, 0xea, 0x92, + 0xa8, 0xd5, 0x7a, 0x34, 0xd8, 0x7d, 0xac, 0x1c, 0x8d, 0xfd, 0x1b, 0x95, 0x4d, 0xfb, + 0x17, 0x70, 0x72, 0xfc, 0xbd, 0x1b, 0xa0, 0x7c, 0x28, 0x45, 0x1b, 0xa0, 0x99, 0xd6, + 0x3a, 0xb0, 0xb0, 0x51, 0x6d, 0x41, 0xe4, 0xb4, 0x3f, 0x04, 0xc7, 0xe3, 0xb5, 0x3a, + 0xec, 0xd0, 0xa0, 0x48, 0x34, 0x24, 0x48, 0xa8, 0x17, 0x60, 0xa4, 0x1e, 0x6e, 0x85, + 0x48, 0x02, 0x25, 0x43, 0xd6, 0x39, 0xb8, 0x9e, 0xa7, 0x46, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x77, 0x5c, 0x7f, 0x5c, 0xab, 0x43, 0x86, 0x88, 0x64, 0x3d, 0xdd, 0x15, 0x8d, 0xda, + 0xed, 0xf9, 0xa0, 0xea, 0xef, 0x61, 0x4b, 0x54, 0x90, 0x60, 0xf1, 0xe4, 0xd7, 0xcc, + 0x3e, 0x7e, 0x8b, 0x64, 0x49, 0x9a, 0x81, 0x8a, 0x6d, 0x0e, 0x33, 0x57, 0x68, 0x6e, + 0x65, 0xbc, 0x27, 0x4e, 0x3f, 0x7d, 0x45, 0x5b, 0x91, 0x1f, 0x13, 0x9f, 0x19, 0xf0, + 0x81, 0x61, 0x57, 0x51, 0x91, 0x3e, 0xb4, 0x12, + ], + ovk: [ + 0x45, 0xe1, 0x59, 0x6c, 0xbf, 0x46, 0x70, 0xb7, 0xe0, 0x5d, 0xfd, 0xaf, 0xbb, 0x0c, + 0xf3, 0xdd, 0xee, 0x28, 0xd7, 0x6a, 0x82, 0x42, 0x8e, 0x8a, 0xba, 0x43, 0x64, 0xe8, + 0x4b, 0xac, 0x37, 0x92, + ], + default_d: [ + 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, + ], + default_pk_d: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, + ], + v: 10238534295395242511, + rseed: [ + 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, + 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, + 0xa5, 0xfa, 0x38, 0x5d, + ], + asset: [ + 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, + 0xc4, 0xbd, 0x4f, 0xc9, 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, + 0xf6, 0x99, 0x03, 0x18, + ], + memo: [ + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, 0xe3, 0xa8, 0x54, 0x3e, 0xb9, 0x0a, 0x5e, 0xc0, 0x2f, 0x35, + 0xa7, 0xc6, 0x4b, 0x7d, 0xd5, 0x9a, 0x72, 0xda, 0x00, 0x74, 0x63, 0x4e, 0x01, 0xd2, + 0xab, 0xf3, 0x63, 0x7a, 0xdd, 0x77, 0xc7, 0x35, + ], + cv_net: [ + 0x43, 0x94, 0x47, 0xab, 0x14, 0x5a, 0x6f, 0x0e, 0x5a, 0x3b, 0x43, 0x63, 0x04, 0x4c, + 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, + 0x23, 0x2a, 0xe1, 0x98, + ], + nf_old: [ + 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, + 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, + 0x4e, 0xb3, 0xa2, 0x08, + ], + cmx: [ + 0xb5, 0x62, 0x5f, 0xa5, 0xfb, 0xeb, 0xa7, 0xc9, 0xea, 0xff, 0xff, 0x7d, 0xf4, 0x75, + 0xdc, 0x82, 0x33, 0x22, 0xee, 0x88, 0x01, 0x70, 0x56, 0x45, 0xe5, 0x62, 0x7e, 0x4a, + 0xca, 0x36, 0x6c, 0x02, + ], + esk: [ + 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, 0x44, 0xb0, 0xb0, 0x4f, + 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, 0xa9, 0xec, 0x88, 0x17, + 0x18, 0x65, 0x40, 0x33, + ], + ephemeral_key: [ + 0x51, 0x66, 0x26, 0x31, 0x6e, 0xea, 0x63, 0xa6, 0x45, 0xae, 0x56, 0x23, 0x81, 0x5a, + 0x31, 0x74, 0xb3, 0xed, 0x36, 0x64, 0xc3, 0x3e, 0x6a, 0x51, 0x81, 0xa9, 0xf5, 0xb5, + 0x42, 0x76, 0x7a, 0x2d, + ], + shared_secret: [ + 0xf6, 0x04, 0x23, 0x98, 0x7f, 0x0e, 0x67, 0x6d, 0x1a, 0x3b, 0xb6, 0xef, 0xe0, 0x39, + 0x42, 0x1d, 0xbb, 0xc8, 0x24, 0xb6, 0x90, 0xc1, 0x94, 0xa4, 0x90, 0xe4, 0x17, 0x1d, + 0xde, 0x21, 0x58, 0x19, + ], + k_enc: [ + 0x20, 0x98, 0x25, 0x7e, 0x2b, 0x9b, 0x7f, 0xc0, 0x62, 0x82, 0x38, 0x03, 0x38, 0x59, + 0x7d, 0xcb, 0x62, 0x7d, 0xdf, 0x47, 0x3e, 0x83, 0xa7, 0x2e, 0x61, 0xb0, 0xf2, 0x2c, + 0xcf, 0xaf, 0xbe, 0x4e, + ], + p_enc: [ + 0x03, 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, 0x0f, 0x12, + 0xb0, 0x11, 0xb2, 0x94, 0x16, 0x8e, 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, + 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, + 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, 0xa5, 0xfa, 0x38, 0x5d, 0x76, 0xba, 0x24, 0x3f, + 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, 0xc4, 0xbd, 0x4f, 0xc9, + 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, 0xf6, 0x99, 0x03, 0x18, + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, 0xe3, 0xa8, 0x54, 0x3e, 0xb9, 0x0a, 0x5e, 0xc0, 0x2f, 0x35, + 0xa7, 0xc6, 0x4b, 0x7d, 0xd5, 0x9a, 0x72, 0xda, 0x00, 0x74, 0x63, 0x4e, 0x01, 0xd2, + 0xab, 0xf3, 0x63, 0x7a, 0xdd, 0x77, 0xc7, 0x35, + ], + c_enc: [ + 0xa4, 0x01, 0xab, 0x60, 0x1f, 0x8d, 0x69, 0xd9, 0x38, 0x0c, 0x3d, 0xef, 0x1f, 0x1a, + 0x34, 0xbe, 0x6c, 0xfa, 0x4d, 0x83, 0x8b, 0xf8, 0x7f, 0x00, 0xe3, 0x6b, 0xe6, 0xbe, + 0x68, 0x60, 0xbe, 0xa8, 0x3d, 0xab, 0xdd, 0x00, 0xab, 0xe7, 0xe0, 0xd1, 0x21, 0x90, + 0xfb, 0x54, 0xb0, 0xf2, 0xad, 0xcf, 0xef, 0x9e, 0xf4, 0x2b, 0xa2, 0x31, 0x77, 0x6a, + 0xd3, 0xee, 0x09, 0x86, 0xdb, 0x3f, 0x4f, 0xc0, 0xa8, 0xa1, 0xc6, 0xa7, 0xfe, 0x54, + 0xa6, 0x6b, 0xd7, 0x68, 0xa9, 0xde, 0xd2, 0x5b, 0xb1, 0x89, 0xd5, 0x87, 0x1c, 0xaf, + 0x4d, 0xf8, 0x95, 0x6c, 0x2f, 0x30, 0x70, 0x15, 0x89, 0xa4, 0xdc, 0xdb, 0x68, 0x11, + 0x6d, 0x0f, 0x50, 0x9b, 0x34, 0x1e, 0x8f, 0x25, 0x8e, 0x17, 0x38, 0xb5, 0x51, 0x9c, + 0x99, 0xf1, 0xdb, 0xd0, 0x86, 0x31, 0x56, 0x2f, 0x90, 0xd1, 0x5e, 0x72, 0x8a, 0x85, + 0x25, 0xa1, 0x1b, 0xfe, 0x53, 0x95, 0x24, 0x5d, 0x71, 0x79, 0xcf, 0x8e, 0x97, 0xa8, + 0x3f, 0xaa, 0x4c, 0xf3, 0xb2, 0xa8, 0xb5, 0xef, 0x62, 0x13, 0xe3, 0x30, 0x89, 0xb4, + 0xeb, 0x03, 0xe7, 0xc2, 0xf0, 0x12, 0x11, 0xfc, 0x53, 0xbc, 0x01, 0x16, 0x40, 0x05, + 0x01, 0x5d, 0xbf, 0x33, 0xc6, 0x50, 0xa3, 0xf8, 0x33, 0xba, 0x67, 0x77, 0xcf, 0xf1, + 0xd7, 0x38, 0xe2, 0x1c, 0x58, 0xdc, 0x05, 0xc3, 0xb4, 0xec, 0xb9, 0x7a, 0x6c, 0xe0, + 0xb0, 0xc5, 0xee, 0x94, 0x4c, 0x24, 0xb3, 0x3b, 0xb0, 0xce, 0x32, 0xbe, 0x02, 0x3e, + 0x21, 0x3f, 0xf7, 0xc9, 0xd4, 0x12, 0x4f, 0xc9, 0xdc, 0x4a, 0xa7, 0xca, 0x47, 0x13, + 0x86, 0x48, 0xe2, 0xbb, 0x80, 0x7c, 0xea, 0x7a, 0x58, 0xe7, 0x67, 0xd3, 0x27, 0x07, + 0x4a, 0xe5, 0xe3, 0x9c, 0x3c, 0x17, 0xb7, 0x7c, 0x09, 0x0a, 0xf9, 0x42, 0x5b, 0xc6, + 0x40, 0xd2, 0x1d, 0xd6, 0x81, 0xa6, 0x37, 0x45, 0xe9, 0x02, 0x59, 0xe2, 0xd1, 0x09, + 0x0c, 0x88, 0x48, 0x8e, 0x21, 0x48, 0xb9, 0xee, 0x24, 0x31, 0xc5, 0xae, 0xf5, 0x10, + 0x95, 0xb3, 0x5a, 0x37, 0x7c, 0xfa, 0x76, 0x5d, 0x82, 0x24, 0x98, 0x83, 0x00, 0x04, + 0x71, 0x79, 0xa5, 0x09, 0x40, 0x28, 0xbe, 0x52, 0x7d, 0x5d, 0xe1, 0xc2, 0x69, 0xff, + 0x45, 0x2c, 0x0a, 0xaf, 0x5a, 0x47, 0x7e, 0x93, 0x90, 0xa0, 0xf0, 0xa8, 0x68, 0x11, + 0x3c, 0x7c, 0xd1, 0x9e, 0x2e, 0xac, 0x54, 0x0d, 0xc6, 0x59, 0xda, 0x29, 0x60, 0x06, + 0x77, 0x6e, 0xda, 0x0d, 0xf9, 0x81, 0xc4, 0x11, 0xc1, 0x50, 0x01, 0xa9, 0x8b, 0x6a, + 0xd6, 0x58, 0xd9, 0xa6, 0x4c, 0x12, 0x6a, 0xbe, 0xfc, 0x73, 0x9a, 0xa1, 0xf4, 0x44, + 0xbb, 0x83, 0xf3, 0xf1, 0x4d, 0x11, 0x3d, 0x02, 0x8f, 0xae, 0x10, 0xe4, 0xc5, 0xdb, + 0xe7, 0x78, 0x51, 0x96, 0x83, 0xcd, 0xf4, 0xc2, 0xf4, 0x6c, 0x4a, 0x52, 0xae, 0x12, + 0x09, 0xe1, 0x12, 0x7f, 0x9d, 0xc4, 0xed, 0x86, 0x7d, 0x8e, 0xda, 0x02, 0x4a, 0x68, + 0x9f, 0x6b, 0x15, 0xb8, 0x05, 0x38, 0x03, 0x02, 0x44, 0x02, 0xa1, 0xce, 0x6f, 0x1c, + 0x63, 0x6f, 0x2e, 0xfc, 0xf9, 0xd0, 0x60, 0x51, 0x5c, 0xd6, 0x14, 0x71, 0x8d, 0x51, + 0x52, 0x7d, 0x26, 0x7a, 0xd8, 0x95, 0xfa, 0xd8, 0xec, 0xfb, 0x23, 0x51, 0xf8, 0x92, + 0x45, 0x0d, 0xc8, 0x74, 0xe8, 0x74, 0x39, 0x2c, 0x91, 0xed, 0x3a, 0xf1, 0x18, 0x38, + 0xc4, 0xb5, 0x48, 0x2e, 0x8c, 0x92, 0xeb, 0xc7, 0xa0, 0x08, 0x8e, 0x49, 0xd2, 0xb0, + 0xb4, 0xa1, 0xbd, 0x33, 0x3b, 0x38, 0x7f, 0x49, 0xe3, 0x0f, 0xd2, 0x1a, 0x6e, 0xdc, + 0x89, 0x94, 0x83, 0x4f, 0x28, 0xe9, 0xf2, 0x52, 0x9a, 0x7e, 0x27, 0x24, 0x21, 0x6d, + 0x9e, 0x1a, 0xe5, 0xb4, 0x6e, 0xb1, 0x9a, 0x53, 0xea, 0x2b, 0x97, 0x99, 0x65, 0xf7, + 0x5b, 0x83, 0xf6, 0x86, 0xed, 0xc0, 0x1d, 0x25, 0x7a, 0x06, 0x58, 0xd7, 0x4e, 0x25, + 0xc0, 0xe1, 0xa8, 0xb0, 0x65, 0x60, 0x43, 0x1f, 0x85, 0x10, 0x5c, 0xf9, 0x8a, 0x1f, + 0xfe, 0x28, 0x40, 0x8a, 0x64, 0xf4, 0xc0, 0x27, 0x8d, 0x36, 0xed, 0xea, 0x76, 0x40, + 0xa2, 0x18, 0x26, 0xc3, 0xae, 0xba, 0xcb, 0x41, 0x4d, 0xa1, 0x8c, 0xc1, 0xd1, 0xe8, + 0x64, 0xc1, 0x6e, 0x97, 0x71, 0x0d, 0x56, 0xe0, 0xa1, 0x0e, 0x2c, 0xae, 0x86, 0xcb, + 0x27, 0x50, 0x14, 0x21, 0xdf, 0x52, 0xeb, 0x3c, 0x2f, 0x6e, 0x9d, 0x15, 0x59, 0xc1, + 0xb9, 0x5e, 0x7f, 0x63, 0xcb, 0x5c, 0xfa, 0xf5, 0xca, 0xc1, + ], + ock: [ + 0xc3, 0xd1, 0x04, 0x73, 0x14, 0x50, 0x57, 0x52, 0x3a, 0x55, 0xb7, 0x25, 0xcb, 0x2b, + 0x25, 0xd4, 0xe1, 0xe0, 0x5b, 0xc2, 0xfe, 0x4b, 0xbe, 0xbe, 0xb4, 0xd4, 0x2a, 0x61, + 0x8a, 0xbc, 0xd8, 0xbc, + ], + op: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, + 0x44, 0xb0, 0xb0, 0x4f, 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, + 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, + ], + c_out: [ + 0x74, 0xd2, 0x40, 0xe8, 0xbe, 0x49, 0xb2, 0xa1, 0xad, 0x31, 0x8c, 0xfe, 0xf8, 0x43, + 0x5b, 0x79, 0x7f, 0x71, 0xfa, 0x8b, 0xda, 0x90, 0xed, 0x98, 0x4b, 0x15, 0x69, 0x7c, + 0x3e, 0x34, 0x81, 0x8f, 0x48, 0x96, 0x53, 0x79, 0x0f, 0xe7, 0x04, 0xc8, 0x16, 0x62, + 0xd9, 0xfb, 0x70, 0xde, 0x53, 0x63, 0xca, 0x17, 0xf6, 0x26, 0x2b, 0xae, 0xe2, 0x4b, + 0x2f, 0x2a, 0x80, 0x46, 0x8b, 0x03, 0x94, 0x1f, 0x55, 0x6a, 0x93, 0x0c, 0x37, 0x50, + 0xe6, 0x9a, 0xce, 0xcc, 0x79, 0xc0, 0xe4, 0x72, 0x0f, 0xe5, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x9c, 0xe9, 0x20, 0x37, 0x6a, 0x6a, 0x54, 0x1e, 0x6a, 0xad, 0x66, 0x0e, 0xfa, 0x09, + 0x8d, 0xc5, 0x4c, 0x18, 0xfc, 0xeb, 0x13, 0xd0, 0x99, 0x9f, 0xbc, 0xc7, 0xfd, 0x45, + 0xa5, 0x7c, 0xcc, 0x10, 0xb8, 0xaa, 0x86, 0xc4, 0x54, 0x0d, 0x0a, 0x9f, 0xc6, 0x6d, + 0xf8, 0x5d, 0xad, 0xd6, 0x21, 0x56, 0x36, 0x5e, 0x28, 0xa3, 0xe9, 0x80, 0xb9, 0x8d, + 0x13, 0x1b, 0x50, 0x3a, 0xa0, 0x6a, 0x6c, 0x19, + ], + ovk: [ + 0xf8, 0x1a, 0xd6, 0x17, 0xfa, 0x26, 0xf0, 0xdf, 0xb8, 0x36, 0x55, 0xb8, 0xa2, 0x9a, + 0x7f, 0x83, 0x42, 0x32, 0x42, 0x5e, 0x8c, 0x47, 0x45, 0x88, 0xf1, 0x8d, 0xd3, 0x26, + 0xaa, 0x39, 0x6c, 0x3e, + ], + default_d: [ + 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, + ], + default_pk_d: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, + ], + v: 2690686290017047047, + rseed: [ + 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, + 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, + 0xee, 0xba, 0xe6, 0xfa, + ], + asset: [ + 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, + 0xc3, 0x93, 0x11, 0x78, 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, + 0xe5, 0xf5, 0xd4, 0xbc, + ], + memo: [ + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, 0x4d, 0xfa, 0xfe, 0x87, 0x52, 0x62, 0xdd, 0x7b, 0xe4, 0x1c, + 0xbb, 0xc6, 0x24, 0x20, 0xd4, 0xad, 0x6d, 0xf5, 0xc9, 0xb7, 0x13, 0x60, 0x4f, 0x65, + 0x60, 0x88, 0xa4, 0x48, 0x5e, 0x93, 0xbe, 0x19, + ], + cv_net: [ + 0xf4, 0x5c, 0xba, 0x14, 0x6a, 0xe7, 0x18, 0x85, 0xfd, 0x61, 0xb4, 0xa0, 0xf3, 0x6b, + 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, + 0xa7, 0x20, 0xb8, 0xa6, + ], + nf_old: [ + 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, + 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, + 0x4c, 0x3f, 0x8d, 0x26, + ], + cmx: [ + 0x4c, 0x6c, 0x39, 0xec, 0xcf, 0xc0, 0xce, 0xe9, 0x0b, 0x46, 0xdb, 0x88, 0x98, 0xe0, + 0xd1, 0x8b, 0x2c, 0x7a, 0x61, 0x63, 0x0a, 0xb2, 0x71, 0x5c, 0x77, 0x07, 0x17, 0x37, + 0xca, 0x2a, 0x18, 0x13, + ], + esk: [ + 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, 0xa5, 0xd8, 0x9a, 0xa8, + 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, 0x6a, 0x72, 0xcb, 0x74, + 0xfb, 0x18, 0xd1, 0x17, + ], + ephemeral_key: [ + 0x3c, 0x04, 0xbe, 0x6e, 0x42, 0xa6, 0xca, 0x7f, 0x5d, 0xda, 0x0d, 0x82, 0xdf, 0x30, + 0x7b, 0xd9, 0x6b, 0xb7, 0xb1, 0xae, 0x8d, 0x62, 0x31, 0x87, 0xe3, 0x9c, 0x00, 0xa4, + 0x8c, 0x25, 0xaa, 0x9d, + ], + shared_secret: [ + 0x3a, 0x60, 0x2b, 0xaf, 0xb8, 0xa2, 0x66, 0x5a, 0x74, 0xdf, 0x34, 0xab, 0x6e, 0x3c, + 0x48, 0x8b, 0x09, 0xe2, 0x28, 0x4e, 0xa1, 0x7d, 0x56, 0x02, 0x62, 0xe2, 0x1f, 0x7f, + 0x3c, 0xba, 0xa3, 0x95, + ], + k_enc: [ + 0x1b, 0x6d, 0xd1, 0x03, 0x49, 0x63, 0x67, 0xc9, 0x2b, 0x36, 0x8f, 0xc2, 0xf1, 0xc6, + 0x2e, 0x56, 0xc8, 0xc9, 0xfb, 0xe3, 0x4a, 0x35, 0x84, 0x1f, 0xe1, 0xa3, 0x70, 0x96, + 0x43, 0xe1, 0x35, 0xe1, + ], + p_enc: [ + 0x03, 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, 0x07, 0xd2, + 0x7a, 0xc6, 0xec, 0x3c, 0x57, 0x25, 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, + 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, + 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, 0xee, 0xba, 0xe6, 0xfa, 0x64, 0xd0, 0x87, 0x40, + 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, 0xc3, 0x93, 0x11, 0x78, + 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, 0xe5, 0xf5, 0xd4, 0xbc, + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, 0x4d, 0xfa, 0xfe, 0x87, 0x52, 0x62, 0xdd, 0x7b, 0xe4, 0x1c, + 0xbb, 0xc6, 0x24, 0x20, 0xd4, 0xad, 0x6d, 0xf5, 0xc9, 0xb7, 0x13, 0x60, 0x4f, 0x65, + 0x60, 0x88, 0xa4, 0x48, 0x5e, 0x93, 0xbe, 0x19, + ], + c_enc: [ + 0xb4, 0x15, 0x88, 0x23, 0x1d, 0x6b, 0xa2, 0x9c, 0xc5, 0xb9, 0xaa, 0xf0, 0xc1, 0xf0, + 0xba, 0x44, 0x16, 0x6e, 0xdb, 0x8a, 0x27, 0x29, 0xca, 0xba, 0x53, 0x71, 0xe7, 0xac, + 0x36, 0x90, 0x0f, 0xaa, 0x64, 0xf5, 0x76, 0x0d, 0xce, 0x55, 0x20, 0xda, 0x82, 0x8d, + 0x5e, 0x25, 0xbd, 0x83, 0x51, 0x95, 0x11, 0x64, 0x12, 0x11, 0x80, 0x9d, 0xff, 0xd8, + 0xcf, 0xeb, 0xff, 0xf3, 0xcd, 0xdc, 0xd2, 0x75, 0x88, 0x1e, 0x39, 0xb6, 0x3d, 0xac, + 0x4d, 0x98, 0x6b, 0x10, 0xc0, 0xe4, 0xc5, 0x52, 0x63, 0xde, 0x3e, 0x02, 0x54, 0x94, + 0x81, 0x8a, 0x38, 0x08, 0xd9, 0xab, 0xc6, 0xec, 0x38, 0x8f, 0x95, 0x26, 0x73, 0x95, + 0x0a, 0xa2, 0xd0, 0xe4, 0xba, 0x00, 0x53, 0x75, 0xac, 0x60, 0x5d, 0xc8, 0x25, 0xde, + 0x4d, 0xd8, 0x93, 0x8b, 0x94, 0x7f, 0xf7, 0x19, 0x4c, 0xfe, 0x7c, 0x1d, 0x79, 0xa1, + 0x27, 0x15, 0x5d, 0x11, 0xcb, 0xe3, 0x43, 0xf3, 0x2f, 0xd1, 0x0c, 0x7d, 0xae, 0x39, + 0x1f, 0x00, 0xb4, 0x4f, 0xbe, 0x30, 0x1c, 0x63, 0xfd, 0x4b, 0xf1, 0xc0, 0xdf, 0xb6, + 0xc9, 0xec, 0xb4, 0xc3, 0xf3, 0xfe, 0xf5, 0x40, 0xb6, 0x7e, 0xb9, 0x23, 0x13, 0x71, + 0x9c, 0x5a, 0x30, 0x7a, 0xd3, 0x95, 0x6b, 0xb9, 0x4e, 0x29, 0x86, 0x85, 0x2a, 0x64, + 0x5a, 0x95, 0xd6, 0xdc, 0x75, 0xaa, 0x27, 0x4c, 0xcf, 0xd2, 0x71, 0xd0, 0xea, 0xe2, + 0x65, 0x81, 0xf5, 0xf5, 0x5d, 0x64, 0x74, 0xaa, 0xad, 0x37, 0x4c, 0x86, 0x45, 0x05, + 0xe6, 0x92, 0x37, 0xf6, 0x66, 0x99, 0xee, 0x39, 0xe9, 0xfc, 0xf5, 0xb1, 0xb7, 0x03, + 0x35, 0x1e, 0x71, 0xf6, 0x3b, 0x02, 0x33, 0x40, 0x82, 0xee, 0xbe, 0xd8, 0x68, 0xb5, + 0x61, 0x2a, 0x33, 0x95, 0x78, 0x5a, 0x33, 0x2a, 0x52, 0x43, 0xe4, 0x98, 0x6e, 0x1f, + 0xf5, 0xb4, 0x2d, 0x06, 0x69, 0xc1, 0x5c, 0x45, 0xff, 0x81, 0xe2, 0x2e, 0xea, 0xe4, + 0xde, 0x7d, 0x9a, 0x4f, 0x57, 0x24, 0xc8, 0x96, 0x03, 0x94, 0x92, 0x5b, 0xa1, 0xa1, + 0x90, 0x0f, 0xa2, 0xb5, 0x59, 0x3d, 0x55, 0x45, 0x5e, 0x0b, 0xe0, 0x31, 0x8c, 0x80, + 0x23, 0x81, 0xec, 0x9c, 0x0a, 0x83, 0xc2, 0xe5, 0xf9, 0x33, 0x9f, 0x02, 0x9c, 0x44, + 0x24, 0x72, 0x8f, 0x91, 0x9d, 0x18, 0x4f, 0x36, 0x16, 0x50, 0xba, 0x65, 0xd6, 0x98, + 0xa8, 0xd1, 0x67, 0xbe, 0xd9, 0xdd, 0x01, 0xfa, 0x70, 0x74, 0xe4, 0x6a, 0xf6, 0x57, + 0x16, 0xdd, 0xd9, 0x7e, 0x7b, 0xb6, 0x00, 0x13, 0x05, 0x96, 0x8c, 0xd5, 0xb4, 0x87, + 0x0d, 0xf2, 0x00, 0x42, 0xe7, 0x69, 0xe0, 0x2d, 0xf1, 0x8b, 0x9f, 0xde, 0x9f, 0xda, + 0xa7, 0x6b, 0x00, 0xca, 0x26, 0x45, 0x9d, 0x54, 0x37, 0x19, 0x19, 0x72, 0xd7, 0x08, + 0xde, 0xda, 0xbf, 0x1d, 0x61, 0x7f, 0x73, 0x3a, 0x60, 0xeb, 0xfe, 0xc6, 0xac, 0xf0, + 0x0b, 0xb1, 0xdf, 0xbf, 0x11, 0x2d, 0x3a, 0xaa, 0xc9, 0xfb, 0xd2, 0x30, 0xcc, 0xaa, + 0x9c, 0xf3, 0x58, 0x45, 0x93, 0x54, 0xac, 0x5b, 0x29, 0xbd, 0xb7, 0x3a, 0x45, 0x27, + 0x1b, 0x1f, 0x9e, 0xd0, 0x0e, 0x3e, 0x20, 0xb1, 0x2f, 0xed, 0x5c, 0xd5, 0x6a, 0xbb, + 0xb0, 0xb9, 0x4a, 0x9e, 0xee, 0x5f, 0xf8, 0xf9, 0x36, 0x1d, 0xfd, 0x6c, 0x94, 0x08, + 0x5d, 0x28, 0x98, 0xe5, 0x46, 0xeb, 0x92, 0xe6, 0xdb, 0xe9, 0xf0, 0x2e, 0xb5, 0xbf, + 0x7d, 0x12, 0x67, 0x5d, 0x3c, 0x6a, 0xc7, 0x18, 0x4b, 0x26, 0x01, 0xe4, 0xf4, 0x05, + 0x37, 0x3a, 0x4f, 0x1c, 0x5d, 0xf7, 0x6b, 0x3c, 0xb5, 0x29, 0x99, 0xd8, 0x0f, 0x59, + 0xb3, 0x94, 0xbc, 0xed, 0x9f, 0x66, 0xbc, 0xf7, 0xdc, 0x37, 0xc2, 0xb4, 0xc6, 0xf7, + 0x74, 0x5b, 0xc6, 0xf0, 0x37, 0x74, 0xfa, 0xc6, 0x24, 0x5d, 0x7c, 0x63, 0x6d, 0xfc, + 0x5f, 0x76, 0x58, 0xb2, 0xd2, 0xfd, 0x84, 0xac, 0xa9, 0xe0, 0xef, 0xcd, 0xe0, 0x09, + 0x3e, 0x62, 0x29, 0x38, 0xb7, 0x5d, 0xae, 0x66, 0xcf, 0x63, 0xf6, 0xd2, 0x35, 0x17, + 0x2e, 0x5a, 0x0b, 0xbe, 0xcd, 0x15, 0x56, 0x6c, 0x61, 0xfe, 0x5a, 0x58, 0x94, 0x7c, + 0x18, 0xb9, 0xb5, 0xa1, 0x27, 0x29, 0x4b, 0x67, 0x67, 0xd0, 0x2b, 0x0f, 0x66, 0x4c, + 0xef, 0x25, 0x8e, 0x26, 0x11, 0x1c, 0xf0, 0x9c, 0x9b, 0x61, 0xd4, 0x41, 0x52, 0x8d, + 0x8c, 0xa2, 0xd8, 0x00, 0x5c, 0xad, 0x2a, 0xe4, 0x16, 0xe3, 0x4b, 0xb2, 0x6b, 0x41, + 0xa1, 0x85, 0x5a, 0xf9, 0x90, 0xcd, 0xb6, 0x77, 0xaf, 0x0d, + ], + ock: [ + 0x2b, 0x28, 0x4c, 0xea, 0xca, 0x3e, 0xe7, 0x05, 0x2b, 0xb4, 0xad, 0x16, 0x7e, 0xc4, + 0x4f, 0xbf, 0x14, 0x4f, 0x7a, 0xef, 0x67, 0x8a, 0x37, 0xe6, 0x1e, 0x0b, 0x1f, 0x6b, + 0xdc, 0x24, 0xa0, 0x0d, + ], + op: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, + 0xa5, 0xd8, 0x9a, 0xa8, 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, + 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, + ], + c_out: [ + 0x4b, 0x9a, 0x5a, 0x4a, 0x4d, 0xda, 0x98, 0xfb, 0x92, 0x9a, 0xe9, 0x7b, 0x11, 0xb2, + 0x09, 0xae, 0x23, 0x42, 0x5e, 0x52, 0x26, 0x9a, 0xad, 0xca, 0x13, 0x23, 0x9c, 0xb9, + 0xb3, 0x8f, 0xbf, 0xfb, 0x85, 0x29, 0x58, 0x41, 0xd0, 0xf3, 0x2b, 0xea, 0xd9, 0x2c, + 0x4d, 0x3c, 0x88, 0xe6, 0xe7, 0x2a, 0x1b, 0xe1, 0xd6, 0x64, 0x9b, 0x1c, 0xee, 0x43, + 0x0e, 0xad, 0x38, 0x44, 0x56, 0x07, 0xc4, 0xa9, 0xb6, 0x02, 0x51, 0x83, 0x56, 0x1e, + 0x6c, 0xff, 0x55, 0x2a, 0xf0, 0x88, 0x98, 0xd4, 0x09, 0xa6, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xb4, 0x9e, 0x3c, 0x5b, 0xb9, 0x9e, 0x47, 0xc5, 0x3d, 0x6e, 0x5c, 0x34, 0x7c, 0x99, + 0x8f, 0x30, 0x2d, 0x3f, 0xf4, 0x75, 0x23, 0xe7, 0xc3, 0xd7, 0xb6, 0x4c, 0x82, 0x98, + 0xdc, 0x7b, 0x10, 0xe9, 0x54, 0xdf, 0x06, 0x00, 0x0b, 0xc0, 0xcc, 0x30, 0xec, 0xf6, + 0x75, 0x5d, 0x92, 0x7e, 0xee, 0xce, 0xe6, 0xec, 0x9e, 0x8e, 0x0c, 0xba, 0xa3, 0x1b, + 0x71, 0xe0, 0xa4, 0x33, 0x4a, 0xd6, 0x42, 0x1b, + ], + ovk: [ + 0x97, 0x9f, 0x06, 0x58, 0x66, 0x73, 0xbc, 0x6f, 0xf1, 0xc5, 0xd3, 0xb3, 0x20, 0xf3, + 0x49, 0xa5, 0xb3, 0xa8, 0xb3, 0x55, 0x59, 0x22, 0x96, 0xaa, 0xf6, 0x1c, 0x5b, 0x72, + 0x52, 0xf7, 0x3e, 0xc0, + ], + default_d: [ + 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, + ], + default_pk_d: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, + ], + v: 5531329397987978327, + rseed: [ + 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, + 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, + 0xd0, 0x11, 0x8b, 0xbd, + ], + asset: [ + 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, + 0xe3, 0x7a, 0x83, 0xec, 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, + 0x29, 0x03, 0x35, 0xaa, + ], + memo: [ + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, 0xa8, 0xf2, 0xdc, 0x53, 0xf4, 0x6f, 0x6c, 0x9b, 0x07, 0xad, + 0xdf, 0x14, 0x6f, 0x4f, 0xfa, 0x50, 0x1f, 0x9d, 0xd3, 0xcf, 0xf9, 0x24, 0xe3, 0x01, + 0x0f, 0xaf, 0x50, 0x4e, 0x2b, 0x8a, 0xca, 0x73, + ], + cv_net: [ + 0x1a, 0xa2, 0x3d, 0x96, 0x79, 0xbc, 0x66, 0x04, 0xb6, 0x25, 0x2c, 0x4f, 0x48, 0x1b, + 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, + 0x7e, 0x33, 0x2a, 0x0d, + ], + nf_old: [ + 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, + 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, + 0x4b, 0xc8, 0x45, 0x10, + ], + cmx: [ + 0x06, 0x65, 0x7e, 0xd7, 0x3d, 0x2a, 0x26, 0xfa, 0xfd, 0xe2, 0xb5, 0xb3, 0x73, 0xf4, + 0x60, 0x07, 0x89, 0xf5, 0x23, 0x2b, 0x57, 0x3b, 0x4e, 0xcf, 0xd5, 0x3c, 0x14, 0x03, + 0x9b, 0xeb, 0x15, 0x1c, + ], + esk: [ + 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, 0xa1, 0xe6, 0xfb, 0x57, + 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, 0xb9, 0x5f, 0xc8, 0x7e, + 0xa7, 0x37, 0x3e, 0x2f, + ], + ephemeral_key: [ + 0xda, 0x72, 0x84, 0xa0, 0xe0, 0xde, 0x52, 0x09, 0x3c, 0xc2, 0xe1, 0x9c, 0x0a, 0xf1, + 0x93, 0xbd, 0xb4, 0x2c, 0x80, 0xc9, 0xc7, 0xf9, 0xf2, 0x36, 0x00, 0xe6, 0x08, 0x01, + 0x72, 0xc5, 0xf5, 0x39, + ], + shared_secret: [ + 0x9b, 0xcf, 0xb9, 0x6f, 0x4c, 0xf1, 0x83, 0xc1, 0x7f, 0xb1, 0x99, 0xda, 0x16, 0x5f, + 0xbf, 0x8a, 0x47, 0x47, 0x7e, 0x00, 0x36, 0x6d, 0x1c, 0xb7, 0x3b, 0x32, 0xec, 0x0e, + 0x3a, 0xc1, 0x98, 0x0f, + ], + k_enc: [ + 0x21, 0xe0, 0x97, 0x87, 0x0a, 0xee, 0xc0, 0x19, 0x76, 0x86, 0xee, 0x37, 0x22, 0x78, + 0xfe, 0x4a, 0xa2, 0x23, 0x8d, 0x87, 0x65, 0x32, 0x63, 0x84, 0x8a, 0x2f, 0xf5, 0x27, + 0x9f, 0x2b, 0x1d, 0x9b, + ], + p_enc: [ + 0x03, 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, 0x57, 0xac, + 0xbf, 0xfe, 0xc7, 0x3a, 0xc3, 0x4c, 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, + 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, + 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, 0xd0, 0x11, 0x8b, 0xbd, 0xc3, 0xcc, 0x4f, 0x43, + 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, 0xe3, 0x7a, 0x83, 0xec, + 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, 0x29, 0x03, 0x35, 0xaa, + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, 0xa8, 0xf2, 0xdc, 0x53, 0xf4, 0x6f, 0x6c, 0x9b, 0x07, 0xad, + 0xdf, 0x14, 0x6f, 0x4f, 0xfa, 0x50, 0x1f, 0x9d, 0xd3, 0xcf, 0xf9, 0x24, 0xe3, 0x01, + 0x0f, 0xaf, 0x50, 0x4e, 0x2b, 0x8a, 0xca, 0x73, + ], + c_enc: [ + 0x13, 0xd7, 0xdf, 0xcd, 0x1d, 0x75, 0x4d, 0xcd, 0x16, 0x52, 0x32, 0x83, 0x8f, 0x14, + 0xdd, 0x80, 0x5e, 0x12, 0xcc, 0x7e, 0x75, 0x15, 0x43, 0xd2, 0xa6, 0x8e, 0x23, 0x7a, + 0x92, 0x3b, 0xce, 0xeb, 0xa3, 0x5a, 0x62, 0x43, 0xc6, 0xa4, 0xc5, 0xf0, 0xd2, 0xa4, + 0xc3, 0x86, 0x07, 0xa6, 0xf1, 0x1b, 0x17, 0xfd, 0xd6, 0xc6, 0x92, 0x66, 0xf2, 0xc9, + 0x6a, 0xdc, 0x44, 0x6f, 0x2e, 0x2d, 0x07, 0x3e, 0xe9, 0xea, 0xe2, 0x9a, 0x37, 0xef, + 0x5d, 0x03, 0xf6, 0x78, 0xf5, 0x56, 0x29, 0x45, 0xb2, 0x08, 0x27, 0x76, 0xce, 0x9f, + 0x39, 0x08, 0x87, 0x3a, 0x99, 0xa6, 0xa2, 0x8b, 0xae, 0xdc, 0x7f, 0x54, 0x89, 0xce, + 0x4b, 0x30, 0xd8, 0x43, 0x66, 0xc5, 0x46, 0xb4, 0x36, 0x67, 0x91, 0x44, 0xf9, 0x27, + 0xf7, 0x1c, 0x65, 0x09, 0x69, 0xda, 0x22, 0x42, 0x28, 0x5a, 0x86, 0x27, 0x96, 0x54, + 0x89, 0xb7, 0x0b, 0x35, 0x6c, 0xf7, 0x4e, 0x07, 0x8a, 0xa2, 0x7d, 0xa8, 0xf9, 0x2f, + 0xb3, 0x09, 0x57, 0x12, 0x62, 0xf2, 0xd4, 0xc3, 0x36, 0xf7, 0x12, 0x15, 0x9b, 0x3e, + 0x9b, 0x43, 0x24, 0x38, 0x5b, 0xb3, 0x26, 0x2a, 0xc5, 0xf3, 0x13, 0x57, 0xaf, 0x9e, + 0x1a, 0xaa, 0x75, 0xd0, 0x1c, 0x06, 0x31, 0xbf, 0xdd, 0x34, 0xc5, 0x9b, 0x27, 0xd5, + 0x3b, 0xeb, 0xf1, 0xaa, 0x54, 0xe9, 0xc4, 0xaa, 0x98, 0x0f, 0x24, 0x7b, 0xf4, 0x22, + 0xa0, 0xe6, 0xdb, 0xf5, 0x54, 0x6e, 0xdc, 0x10, 0x0f, 0xce, 0x6c, 0xce, 0xc8, 0x32, + 0x7e, 0xb4, 0x8a, 0x9a, 0x39, 0xe4, 0xc2, 0xa9, 0x12, 0xb2, 0x98, 0x85, 0xe0, 0xc3, + 0xe7, 0x33, 0x55, 0x58, 0xbd, 0x85, 0x84, 0x38, 0xd0, 0x35, 0xd2, 0xf2, 0xbe, 0x1d, + 0x35, 0x66, 0xe4, 0x22, 0xfe, 0x37, 0xc0, 0xcb, 0x2e, 0x05, 0x8d, 0xad, 0x8c, 0xc6, + 0x45, 0x62, 0xa5, 0x50, 0x1b, 0x54, 0xa4, 0x4f, 0x9a, 0x77, 0x77, 0xc6, 0xd2, 0x77, + 0x04, 0xa4, 0xce, 0xad, 0x26, 0xa1, 0xc2, 0x56, 0x01, 0x8d, 0xc1, 0xbb, 0xfa, 0x58, + 0x84, 0xa0, 0x6c, 0xc7, 0x25, 0x23, 0xaf, 0xfb, 0x43, 0xf5, 0xc5, 0xbc, 0x2f, 0x1d, + 0x36, 0x04, 0x0f, 0x85, 0xf7, 0xe8, 0xc0, 0x62, 0xc1, 0xf2, 0x26, 0x50, 0x9d, 0x20, + 0xf9, 0xa4, 0x88, 0x5e, 0x15, 0x70, 0x4f, 0x73, 0x01, 0xdf, 0x60, 0x3d, 0xa1, 0xfc, + 0x5b, 0xca, 0x84, 0xf8, 0x55, 0xc1, 0x17, 0xcb, 0x30, 0x55, 0xc5, 0x70, 0x83, 0x45, + 0x7e, 0x1d, 0x14, 0x85, 0x7c, 0x2b, 0xf9, 0x41, 0xe8, 0x20, 0x73, 0x5c, 0x58, 0x8a, + 0xae, 0x6f, 0x66, 0x45, 0xdc, 0x3f, 0xbd, 0x30, 0x65, 0xab, 0xa1, 0x7f, 0xd2, 0x48, + 0x2a, 0x1b, 0x37, 0xb2, 0xf3, 0x88, 0x07, 0x5e, 0x46, 0xbb, 0x9d, 0x37, 0x27, 0xcc, + 0x73, 0xdb, 0xae, 0x0e, 0x96, 0xa8, 0x44, 0x5f, 0xda, 0x8f, 0x87, 0x64, 0xf9, 0x68, + 0x0b, 0xf6, 0xc5, 0x91, 0xa8, 0x48, 0x10, 0xfa, 0x0c, 0x1b, 0x5a, 0x2f, 0x2a, 0xa9, + 0xad, 0xbb, 0x88, 0x64, 0x22, 0x31, 0x72, 0x1e, 0xd6, 0xea, 0x12, 0x16, 0xab, 0x9b, + 0xfa, 0x0e, 0x12, 0x4c, 0xe4, 0x74, 0x94, 0x44, 0x53, 0x4d, 0x68, 0x70, 0x19, 0x74, + 0x60, 0xf7, 0x49, 0xef, 0xb0, 0x28, 0x8f, 0x96, 0x28, 0x3f, 0xc9, 0x37, 0xef, 0xbb, + 0x14, 0x59, 0xaa, 0x73, 0xc2, 0x7b, 0x6b, 0x2b, 0x5c, 0x57, 0x7d, 0x46, 0x60, 0xf9, + 0x8e, 0x81, 0x8c, 0xaa, 0xad, 0xbe, 0x45, 0x4e, 0xcd, 0x16, 0xc1, 0xd8, 0xa9, 0x9b, + 0x77, 0x97, 0x8e, 0x93, 0xd6, 0x9d, 0xcb, 0x8b, 0xf0, 0xe8, 0x4a, 0x0a, 0x91, 0x3f, + 0x55, 0xcc, 0x16, 0x50, 0xc2, 0xb9, 0x2d, 0x4c, 0x9d, 0xcd, 0xb1, 0x2e, 0xe2, 0x36, + 0x7e, 0xd9, 0x79, 0xb9, 0x53, 0x5f, 0xe1, 0x5c, 0x87, 0xd1, 0x7f, 0x37, 0xa3, 0x24, + 0x84, 0x7f, 0x16, 0x45, 0x39, 0x75, 0x7d, 0x83, 0x00, 0x87, 0xf6, 0x39, 0xeb, 0x6c, + 0x3e, 0xfb, 0x8d, 0xa4, 0xff, 0xa5, 0xd7, 0xca, 0x58, 0x34, 0x4d, 0x65, 0x81, 0x76, + 0x64, 0xa7, 0x4e, 0xaf, 0xa1, 0xa4, 0x7f, 0x69, 0xf1, 0xc8, 0x10, 0x6b, 0x6f, 0x5f, + 0x96, 0x4f, 0x4c, 0x73, 0xed, 0xed, 0xb1, 0xe1, 0x25, 0xde, 0xb2, 0x28, 0xc5, 0x62, + 0xfd, 0xc1, 0x87, 0x41, 0x41, 0xa9, 0x7c, 0x62, 0x58, 0x16, 0xc0, 0xcf, 0xeb, 0x83, + 0x84, 0x28, 0x7f, 0x6b, 0x2d, 0x5f, 0xa1, 0x81, 0x89, 0xe1, 0x4f, 0x91, 0xdf, 0x72, + 0x4e, 0x59, 0x80, 0x45, 0x8c, 0x51, 0xfb, 0x1c, 0xd8, 0x46, + ], + ock: [ + 0x59, 0xb8, 0x10, 0x2e, 0x91, 0x7f, 0xf5, 0xa4, 0x23, 0x60, 0x50, 0x7c, 0xce, 0x30, + 0xcc, 0x5b, 0xda, 0xb7, 0x76, 0x18, 0x61, 0x9f, 0x52, 0xda, 0xfa, 0xbd, 0xf5, 0x5a, + 0x3f, 0x64, 0xc1, 0xee, + ], + op: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, + 0xa1, 0xe6, 0xfb, 0x57, 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, + 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, + ], + c_out: [ + 0x7e, 0xaf, 0x92, 0x5e, 0x3e, 0x5c, 0xd2, 0x0c, 0xc9, 0x34, 0x9f, 0x17, 0x4b, 0xdc, + 0x8c, 0x46, 0x45, 0x65, 0xb8, 0x04, 0x68, 0x9d, 0x79, 0x8d, 0x63, 0x2f, 0x58, 0xaa, + 0x26, 0x7a, 0x2f, 0x4e, 0x65, 0xed, 0x07, 0x33, 0xc4, 0x18, 0x67, 0x7b, 0xda, 0x1a, + 0xf5, 0x6e, 0xa9, 0xfd, 0xec, 0xcc, 0xcc, 0xdc, 0x10, 0xa9, 0xb6, 0xda, 0xa4, 0x92, + 0x4b, 0x46, 0x2f, 0x1e, 0x9d, 0x08, 0x65, 0xba, 0xc3, 0xab, 0x71, 0x7a, 0xb8, 0x4f, + 0x54, 0x2c, 0x2f, 0x8d, 0x46, 0xe3, 0x20, 0x5f, 0xb0, 0x33, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xa6, 0x68, 0x13, 0x52, 0xa3, 0x52, 0x26, 0x91, 0x10, 0x0f, 0x53, 0xfc, 0x34, 0xab, + 0x73, 0x32, 0x8a, 0xf1, 0xb9, 0xf3, 0xa4, 0xa0, 0x6d, 0xbd, 0x3a, 0x14, 0x99, 0x67, + 0x09, 0xe6, 0xf2, 0x84, 0x31, 0xee, 0x72, 0xf2, 0x69, 0xae, 0xd7, 0x5d, 0x36, 0x34, + 0x89, 0x36, 0x90, 0x5e, 0xbb, 0x91, 0x80, 0x7d, 0x74, 0xd5, 0x0c, 0xb2, 0x7f, 0xcd, + 0x8b, 0x4f, 0xb6, 0xf4, 0x48, 0xc3, 0x62, 0x03, + ], + ovk: [ + 0x78, 0xf1, 0x45, 0xea, 0x29, 0xd2, 0x71, 0xb9, 0x40, 0xc6, 0x99, 0x41, 0xe4, 0xc3, + 0xfd, 0x2d, 0x71, 0xf3, 0xb1, 0x90, 0x69, 0x0e, 0xe1, 0x6f, 0x5d, 0x14, 0xac, 0x22, + 0x24, 0xe6, 0xfc, 0x89, + ], + default_d: [ + 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, + ], + default_pk_d: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, + ], + v: 15093716717054627455, + rseed: [ + 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, + 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, + 0x24, 0x57, 0x16, 0xa4, + ], + asset: [ + 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, + 0xab, 0xcf, 0xac, 0x88, 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, + 0x07, 0x2d, 0x2d, 0x18, + ], + memo: [ + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, 0xf6, 0xe1, 0x70, 0x81, 0xd5, 0x81, 0x8e, 0x88, 0xb1, 0x4e, + 0x4f, 0x60, 0x1b, 0x8c, 0x06, 0x3e, 0x3f, 0x43, 0x87, 0xff, 0xa2, 0x32, 0x2a, 0x51, + 0x81, 0x90, 0x9f, 0x09, 0x80, 0xd6, 0x89, 0xde, + ], + cv_net: [ + 0x91, 0x6d, 0xc3, 0x82, 0x2a, 0x4e, 0x3b, 0xb4, 0x1f, 0xa8, 0x33, 0xc2, 0x73, 0xa9, + 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, + 0x29, 0x55, 0x39, 0x1c, + ], + nf_old: [ + 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, + 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, + 0x7f, 0x28, 0x4b, 0x2e, + ], + cmx: [ + 0x7a, 0xd4, 0xd8, 0xf5, 0xd4, 0xe7, 0xa9, 0x79, 0xfa, 0x73, 0x93, 0xed, 0x26, 0xf1, + 0x7d, 0x14, 0x2b, 0x65, 0xf5, 0x3b, 0xb4, 0x6d, 0xa6, 0x0a, 0x50, 0x22, 0x28, 0xc0, + 0x7b, 0x2c, 0xda, 0x27, + ], + esk: [ + 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, 0x02, 0xf5, 0x10, 0xe9, + 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, 0xc4, 0x69, 0x2d, 0x0c, + 0x1b, 0x30, 0x33, 0x01, + ], + ephemeral_key: [ + 0x27, 0xcb, 0x40, 0x68, 0x0f, 0xb1, 0xd9, 0x19, 0x64, 0x6e, 0x74, 0x20, 0xe6, 0xa8, + 0xb5, 0x20, 0xe1, 0x9a, 0x17, 0x3f, 0x1e, 0x79, 0x4d, 0x2b, 0x49, 0x2b, 0xfa, 0xbb, + 0x83, 0xce, 0x6c, 0xa0, + ], + shared_secret: [ + 0x1c, 0xd0, 0x66, 0x91, 0x6c, 0x19, 0xfa, 0x33, 0x69, 0xaa, 0x3c, 0x6a, 0x53, 0x76, + 0x97, 0xf4, 0xb4, 0x26, 0x44, 0xda, 0x20, 0xca, 0x46, 0x79, 0x93, 0x2b, 0x7c, 0x90, + 0x5f, 0x2d, 0x69, 0x00, + ], + k_enc: [ + 0xce, 0x9d, 0x22, 0x0d, 0x3a, 0xfe, 0xc6, 0x23, 0x21, 0xdd, 0xf1, 0x97, 0xa6, 0x36, + 0xdc, 0xb3, 0x45, 0x58, 0x83, 0xb7, 0x35, 0x82, 0x8c, 0x65, 0xe7, 0x16, 0x6c, 0x15, + 0xd8, 0xcc, 0xfc, 0xf9, + ], + p_enc: [ + 0x03, 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, 0x7f, 0x8e, + 0x6a, 0x5c, 0x62, 0xa7, 0x77, 0xd1, 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, + 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, + 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, 0x24, 0x57, 0x16, 0xa4, 0x96, 0x86, 0xaa, 0x36, + 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, 0xab, 0xcf, 0xac, 0x88, + 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, 0x07, 0x2d, 0x2d, 0x18, + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, 0xf6, 0xe1, 0x70, 0x81, 0xd5, 0x81, 0x8e, 0x88, 0xb1, 0x4e, + 0x4f, 0x60, 0x1b, 0x8c, 0x06, 0x3e, 0x3f, 0x43, 0x87, 0xff, 0xa2, 0x32, 0x2a, 0x51, + 0x81, 0x90, 0x9f, 0x09, 0x80, 0xd6, 0x89, 0xde, + ], + c_enc: [ + 0xb1, 0x69, 0x64, 0x77, 0xe6, 0x58, 0xb6, 0xf8, 0xe2, 0x4e, 0x02, 0x55, 0x52, 0xb4, + 0x8d, 0xd4, 0x84, 0x58, 0xf2, 0xcd, 0x75, 0x70, 0xc0, 0xe8, 0xce, 0xc4, 0xed, 0x4c, + 0xf7, 0x9b, 0xd5, 0xb6, 0x9e, 0xa8, 0x54, 0x12, 0x3b, 0x4e, 0xaf, 0x97, 0x8b, 0x14, + 0x2e, 0xb3, 0xef, 0x53, 0xaa, 0xfc, 0x78, 0x90, 0xdd, 0xa2, 0x8a, 0xfa, 0x25, 0xf1, + 0x45, 0xc8, 0xb9, 0x7f, 0x7b, 0x94, 0x50, 0xc1, 0xd5, 0xe0, 0xc3, 0x7d, 0xaf, 0x5e, + 0xd4, 0xec, 0xd9, 0xb6, 0x3d, 0xbc, 0xd2, 0x15, 0x11, 0x23, 0x13, 0x9b, 0xbc, 0x2b, + 0x65, 0x1a, 0x8f, 0x69, 0xcf, 0xbf, 0xb7, 0xcb, 0x60, 0x44, 0x78, 0xf3, 0xf2, 0x64, + 0xd9, 0xdd, 0x75, 0xcf, 0x31, 0x9e, 0x3e, 0xcd, 0xf5, 0xb3, 0x34, 0x26, 0x54, 0x85, + 0x7c, 0x52, 0xa1, 0xfc, 0x61, 0x40, 0x55, 0xa2, 0x46, 0xf5, 0x26, 0x3e, 0x85, 0x36, + 0x83, 0xef, 0x54, 0x41, 0x3b, 0xac, 0x99, 0x1a, 0xe6, 0x35, 0x01, 0x50, 0xe1, 0x34, + 0x52, 0xa3, 0xa6, 0x20, 0xc5, 0x3f, 0x80, 0xda, 0xcc, 0x7a, 0xf0, 0x59, 0x26, 0xd9, + 0xc5, 0x9a, 0x94, 0xe4, 0x78, 0x9a, 0xcc, 0x68, 0xd8, 0x51, 0x05, 0x6b, 0x75, 0xa7, + 0x4e, 0x2e, 0x1b, 0x38, 0xbf, 0xcb, 0x6d, 0xba, 0xab, 0x37, 0xa3, 0x8a, 0xe0, 0x2c, + 0x9c, 0x35, 0x25, 0x9e, 0x52, 0x84, 0xe4, 0xfe, 0x83, 0xdd, 0xb2, 0x29, 0x24, 0xa1, + 0xc4, 0x0a, 0xa2, 0x5e, 0xd1, 0xf5, 0xc0, 0x6d, 0xa1, 0x58, 0x31, 0xf0, 0x41, 0x50, + 0xa3, 0x7c, 0x1b, 0xa3, 0xd1, 0x17, 0x04, 0x93, 0xca, 0x29, 0xf3, 0x43, 0x4a, 0xfa, + 0x06, 0x9b, 0x46, 0xaf, 0xdc, 0x87, 0x0a, 0x29, 0x6f, 0xdc, 0x0e, 0xb6, 0x1b, 0x55, + 0x70, 0x77, 0xa1, 0xda, 0x1f, 0xe8, 0x22, 0xb6, 0xce, 0x24, 0x7c, 0x8e, 0x19, 0x9f, + 0xc4, 0x85, 0x14, 0x6f, 0x38, 0x4a, 0xcf, 0x5c, 0x52, 0x69, 0x7e, 0xfa, 0xcc, 0x5b, + 0xfe, 0x42, 0x02, 0xe8, 0x5f, 0x06, 0x4b, 0xc8, 0xe1, 0x2e, 0xee, 0x39, 0x79, 0x6d, + 0xfd, 0x13, 0x99, 0xb1, 0xc1, 0xe8, 0xc7, 0x4b, 0x5e, 0xc3, 0xc3, 0x1d, 0x2c, 0xfa, + 0x44, 0x87, 0x02, 0x5c, 0xeb, 0x5d, 0xb3, 0x55, 0x9d, 0x4b, 0x7b, 0xac, 0x02, 0x73, + 0xf1, 0x33, 0x51, 0xd2, 0xd1, 0x3c, 0xec, 0x0a, 0x44, 0x8c, 0x00, 0x11, 0x09, 0x45, + 0x2c, 0x40, 0x92, 0xc8, 0x11, 0x91, 0xa0, 0xda, 0xa9, 0x79, 0xe2, 0x6a, 0x96, 0x24, + 0xe4, 0x0c, 0xa4, 0xac, 0xcb, 0x63, 0x46, 0xaa, 0xe1, 0x88, 0xca, 0x09, 0x39, 0xdd, + 0x9f, 0x6b, 0x6e, 0x45, 0xe4, 0x1b, 0xca, 0xeb, 0xdc, 0x1d, 0xa8, 0x01, 0xcc, 0xd4, + 0xdc, 0x93, 0x32, 0x26, 0x6f, 0xb3, 0xeb, 0x23, 0x7b, 0x07, 0x72, 0x45, 0xa7, 0x91, + 0xec, 0xb4, 0x0e, 0x5c, 0x40, 0x56, 0xad, 0xd6, 0xb1, 0xb5, 0xf7, 0xf8, 0xfa, 0x10, + 0x4f, 0xba, 0x61, 0x3e, 0xd9, 0x29, 0xe1, 0xfa, 0xd2, 0x26, 0x47, 0x50, 0x35, 0xb6, + 0x1a, 0x9f, 0x85, 0xaf, 0xba, 0xfb, 0x16, 0x6b, 0x24, 0xc2, 0x4d, 0x2c, 0x28, 0x93, + 0x7b, 0x17, 0x70, 0xba, 0x26, 0x9c, 0x15, 0xeb, 0x2d, 0x9b, 0xdc, 0x2b, 0x83, 0xea, + 0xd8, 0xa0, 0x1d, 0xdb, 0x11, 0x08, 0x3b, 0x13, 0xd6, 0x2d, 0x57, 0x2c, 0xf7, 0x8d, + 0x5c, 0xba, 0x6f, 0x36, 0x52, 0xca, 0xc4, 0xd2, 0x4c, 0x71, 0xc5, 0x47, 0x27, 0x26, + 0x24, 0xc0, 0x78, 0xe0, 0xb9, 0x69, 0x68, 0xfe, 0x09, 0xd8, 0x3e, 0xf7, 0x30, 0x20, + 0x62, 0xbb, 0x5d, 0x3a, 0x2c, 0xcf, 0x73, 0x4e, 0x0f, 0xd3, 0x51, 0x01, 0xfd, 0x58, + 0x64, 0x73, 0x3f, 0x44, 0xd0, 0x75, 0xc3, 0x8b, 0x73, 0xf6, 0xbf, 0xb8, 0xc3, 0x9c, + 0x7b, 0x6b, 0x3d, 0xbc, 0xd1, 0x9a, 0x05, 0x89, 0x91, 0x86, 0x37, 0xf7, 0x5b, 0xbe, + 0x40, 0x15, 0x7b, 0x80, 0xe5, 0x9e, 0x55, 0x58, 0x50, 0x28, 0xa5, 0xec, 0x20, 0x1e, + 0x00, 0x8f, 0xf6, 0xf5, 0x12, 0xe2, 0x53, 0xcc, 0x9a, 0xcf, 0x62, 0x7d, 0x94, 0x35, + 0xdb, 0x6b, 0x14, 0xb9, 0x82, 0x48, 0x79, 0xf4, 0xe4, 0x0a, 0x36, 0xd5, 0xec, 0x94, + 0x2b, 0xff, 0x04, 0xfd, 0x0b, 0xb8, 0x0c, 0x3e, 0xdd, 0xb7, 0xb2, 0x0a, 0x11, 0x6b, + 0xa7, 0x0d, 0x84, 0x84, 0x6e, 0xc6, 0xd2, 0x52, 0x0f, 0xe7, 0x68, 0x89, 0x9e, 0xd5, + 0x27, 0xd3, 0x1d, 0x32, 0x19, 0x68, 0xde, 0xc1, 0x32, 0x7b, 0x81, 0xcc, 0x61, 0x89, + 0x8f, 0x2c, 0xc4, 0x5a, 0xeb, 0x43, 0x52, 0x9e, 0x7d, 0x08, + ], + ock: [ + 0x89, 0x5c, 0x90, 0x04, 0xec, 0x4c, 0x50, 0xd6, 0xd5, 0xfd, 0x6a, 0x51, 0x71, 0x2a, + 0xcc, 0xa4, 0x77, 0x1e, 0x1c, 0xe0, 0xb9, 0x94, 0x30, 0xf0, 0x45, 0x9d, 0x43, 0xff, + 0x16, 0x6a, 0x93, 0xf8, + ], + op: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, + 0x02, 0xf5, 0x10, 0xe9, 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, + 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, + ], + c_out: [ + 0xc7, 0xf4, 0x90, 0x67, 0x45, 0x7f, 0x0c, 0xa0, 0xbf, 0x73, 0x0e, 0x55, 0x17, 0x06, + 0x7d, 0x49, 0x39, 0x9a, 0xce, 0xb7, 0xa6, 0x32, 0x85, 0x34, 0x63, 0x90, 0x76, 0xc1, + 0x44, 0xb2, 0x96, 0xc4, 0xce, 0xd1, 0x5a, 0x49, 0xd3, 0xba, 0xe5, 0x8e, 0xc5, 0xf8, + 0xc0, 0xb5, 0x48, 0x06, 0x33, 0x4e, 0x63, 0xc1, 0x14, 0x1c, 0xb8, 0xd3, 0x04, 0x49, + 0x2a, 0xf5, 0xff, 0x0b, 0x5c, 0x14, 0x75, 0x8d, 0x45, 0x60, 0x30, 0x82, 0x0a, 0xbd, + 0xd6, 0x8f, 0x2e, 0x67, 0xa5, 0x87, 0xb2, 0x60, 0xf0, 0x48, + ], + }, + ] +} diff --git a/src/tree.rs b/src/tree.rs index 352974672..a10de6ea5 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -84,7 +84,7 @@ impl Anchor { /// The Merkle path from a leaf of the note commitment tree /// to its anchor. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct MerklePath { position: u32, auth_path: [MerkleHashOrchard; MERKLE_DEPTH_ORCHARD], diff --git a/src/value.rs b/src/value.rs index 9ac440eeb..e8ab3365b 100644 --- a/src/value.rs +++ b/src/value.rs @@ -40,6 +40,7 @@ use core::fmt::{self, Debug}; use core::iter::Sum; use core::ops::{Add, RangeInclusive, Sub}; +use std::ops::Neg; use bitvec::{array::BitArray, order::Lsb0}; use ff::{Field, PrimeField}; @@ -53,12 +54,13 @@ use rand::RngCore; use subtle::CtOption; use crate::{ - constants::fixed_bases::{ - VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES, - }, + constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES}, primitives::redpallas::{self, Binding}, }; +use crate::builder::BuildError; +use crate::note::AssetBase; + /// Maximum note value. pub const MAX_NOTE_VALUE: u64 = u64::MAX; @@ -105,17 +107,24 @@ impl NoteValue { NoteValue(value) } - pub(crate) fn from_bytes(bytes: [u8; 8]) -> Self { + /// Creates a note value from a byte array. + pub fn from_bytes(bytes: [u8; 8]) -> Self { NoteValue(u64::from_le_bytes(bytes)) } - pub(crate) fn to_bytes(self) -> [u8; 8] { + /// Converts the note value to a byte array. + pub fn to_bytes(self) -> [u8; 8] { self.0.to_le_bytes() } pub(crate) fn to_le_bits(self) -> BitArray<[u8; 8], Lsb0> { BitArray::<_, Lsb0>::new(self.0.to_le_bytes()) } + + /// The minimum, greater than zero, note value that can not be split further. + pub fn unsplittable() -> Self { + NoteValue(1u64) + } } impl From<&NoteValue> for Assigned { @@ -124,6 +133,12 @@ impl From<&NoteValue> for Assigned { } } +impl From for i128 { + fn from(value: NoteValue) -> Self { + value.0 as i128 + } +} + impl Sub for NoteValue { type Output = ValueSum; @@ -138,6 +153,14 @@ impl Sub for NoteValue { } } +impl Add for NoteValue { + type Output = Option; + + fn add(self, rhs: Self) -> Self::Output { + self.0.checked_add(rhs.0).map(NoteValue) + } +} + pub(crate) enum Sign { Positive, Negative, @@ -176,29 +199,49 @@ impl ValueSum { sign, ) } + + pub(crate) fn into>(self) -> Result { + i64::try_from(self) + .map_err(BuildError::ValueSum) + .and_then(|i| V::try_from(i).map_err(|_| BuildError::ValueSum(OverflowError))) + } } -impl Add for ValueSum { +impl> Add for ValueSum { type Output = Option; #[allow(clippy::suspicious_arithmetic_impl)] - fn add(self, rhs: Self) -> Self::Output { + fn add(self, rhs: T) -> Self::Output { + self.0 + .checked_add(rhs.into()) + .filter(|v| VALUE_SUM_RANGE.contains(v)) + .map(ValueSum) + } +} + +impl Neg for ValueSum { + type Output = Option; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn neg(self) -> Self::Output { self.0 - .checked_add(rhs.0) + .checked_neg() .filter(|v| VALUE_SUM_RANGE.contains(v)) .map(ValueSum) } } impl<'a> Sum<&'a ValueSum> for Result { - fn sum>(iter: I) -> Self { - iter.fold(Ok(ValueSum(0)), |acc, v| (acc? + *v).ok_or(OverflowError)) + fn sum>(mut iter: I) -> Self { + iter.try_fold(ValueSum(0), |acc, v| acc + *v) + .ok_or(OverflowError) } } impl Sum for Result { - fn sum>(iter: I) -> Self { - iter.fold(Ok(ValueSum(0)), |acc, v| (acc? + v).ok_or(OverflowError)) + fn sum>(mut iter: I) -> Self { + iter.try_fold(ValueSum(0), |acc, v| acc + v) + .ok_or(OverflowError) } } @@ -210,8 +253,20 @@ impl TryFrom for i64 { } } +impl From for i128 { + fn from(value: ValueSum) -> Self { + value.0 + } +} + +impl From for ValueSum { + fn from(value: NoteValue) -> Self { + Self(value.into()) + } +} + /// The blinding factor for a [`ValueCommitment`]. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ValueCommitTrapdoor(pallas::Scalar); impl ValueCommitTrapdoor { @@ -308,9 +363,8 @@ impl ValueCommitment { /// /// [concretehomomorphiccommit]: https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit #[allow(non_snake_case)] - pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor) -> Self { + pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, asset: AssetBase) -> Self { let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); - let V = hasher(&VALUE_COMMITMENT_V_BYTES); let R = hasher(&VALUE_COMMITMENT_R_BYTES); let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); @@ -320,7 +374,9 @@ impl ValueCommitment { pallas::Scalar::from(abs_value) }; - ValueCommitment(V * value + R * rcv.0) + let V_zsa = asset.cv_base(); + + ValueCommitment(V_zsa * value + R * rcv.0) } pub(crate) fn into_bvk(self) -> redpallas::VerificationKey { @@ -424,6 +480,9 @@ pub mod testing { #[cfg(test)] mod tests { + use crate::note::asset_base::testing::{arb_asset_base, native_asset_base}; + + use crate::note::AssetBase; use proptest::prelude::*; use super::{ @@ -432,35 +491,82 @@ mod tests { }; use crate::primitives::redpallas; + fn check_binding_signature( + native_values: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], + arb_values: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], + neg_trapdoors: &[ValueCommitTrapdoor], + arb_values_to_burn: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], + ) { + // for each arb value, create a negative value with a different trapdoor + let neg_arb_values: Vec<_> = arb_values + .iter() + .cloned() + .zip(neg_trapdoors.iter().cloned()) + .map(|((value, _, asset), rcv)| ((-value).unwrap(), rcv, asset)) + .collect(); + + let native_value_balance = native_values + .iter() + .map(|(value, _, _)| value) + .sum::>() + .expect("we generate values that won't overflow"); + + let values = [ + native_values, + arb_values, + &neg_arb_values, + arb_values_to_burn, + ] + .concat(); + + let bsk = values + .iter() + .map(|(_, rcv, _)| rcv) + .sum::() + .into_bsk(); + + let bvk = (values + .into_iter() + .map(|(value, rcv, asset)| ValueCommitment::derive(value, rcv, asset)) + .sum::() + - ValueCommitment::derive( + native_value_balance, + ValueCommitTrapdoor::zero(), + AssetBase::native(), + ) + - arb_values_to_burn + .iter() + .map(|(value, _, asset)| { + ValueCommitment::derive(*value, ValueCommitTrapdoor::zero(), *asset) + }) + .sum::()) + .into_bvk(); + + assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); + } + proptest! { #[test] - fn bsk_consistent_with_bvk( - values in (1usize..10).prop_flat_map(|n_values| + fn bsk_consistent_with_bvk_native_with_zsa_transfer_and_burning( + native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_base()), n_values) ) + ), + (asset_values, neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| + (arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values) + ), prop::collection::vec(arb_trapdoor(), n_values)) + ), + burn_values in (1usize..10).prop_flat_map(|n_values| + arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64) + .prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values)) ) ) { - let value_balance = values - .iter() - .map(|(value, _)| value) - .sum::>() - .expect("we generate values that won't overflow"); - - let bsk = values - .iter() - .map(|(_, rcv)| rcv) - .sum::() - .into_bsk(); - - let bvk = (values - .into_iter() - .map(|(value, rcv)| ValueCommitment::derive(value, rcv)) - .sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero())) - .into_bvk(); - - assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); + check_binding_signature(&native_values, &[], &[], &[]); + check_binding_signature(&native_values, &[], &[], &burn_values); + check_binding_signature(&native_values, &asset_values, &neg_trapdoors, &[]); + check_binding_signature(&native_values, &asset_values, &neg_trapdoors, &burn_values); } } } diff --git a/src/zip32.rs b/src/zip32.rs index 31f318b11..2a036ec9b 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -13,8 +13,11 @@ use crate::{ pub use zip32::ChildIndex; -const ZIP32_ORCHARD_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Orchard"; const ZIP32_ORCHARD_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashOrchardFVFP"; +/// Personalization for the master extended spending key +pub const ZIP32_ORCHARD_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Orchard"; +/// Personalization for the master extended issuance key +pub const ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE: &[u8; 16] = b"ZIP32ZSAIssue_V1"; /// Errors produced in derivation of extended spending keys #[derive(Debug, PartialEq, Eq)] @@ -148,8 +151,12 @@ impl ExtendedSpendingKey { /// # Panics /// /// Panics if seed results in invalid spending key. - pub fn from_path(seed: &[u8], path: &[ChildIndex]) -> Result { - let mut xsk = Self::master(seed)?; + pub fn from_path( + seed: &[u8], + path: &[ChildIndex], + personalization: &[u8; 16], + ) -> Result { + let mut xsk = Self::master(seed, personalization)?; for i in path { xsk = xsk.derive_child(*i)?; } @@ -165,13 +172,13 @@ impl ExtendedSpendingKey { /// # Panics /// /// Panics if the seed is shorter than 32 bytes or longer than 252 bytes. - fn master(seed: &[u8]) -> Result { + fn master(seed: &[u8], personalization: &[u8; 16]) -> Result { assert!(seed.len() >= 32 && seed.len() <= 252); // I := BLAKE2b-512("ZcashIP32Orchard", seed) let I: [u8; 64] = { let mut I = Blake2bParams::new() .hash_length(64) - .personal(ZIP32_ORCHARD_PERSONALIZATION) + .personal(personalization) .to_state(); I.update(seed); I.finalize().as_bytes().try_into().unwrap() @@ -245,7 +252,7 @@ mod tests { #[test] fn derive_child() { let seed = [0; 32]; - let xsk_m = ExtendedSpendingKey::master(&seed).unwrap(); + let xsk_m = ExtendedSpendingKey::master(&seed, ZIP32_ORCHARD_PERSONALIZATION).unwrap(); let i_5 = ChildIndex::hardened(5); let xsk_5 = xsk_m.derive_child(i_5); @@ -256,20 +263,25 @@ mod tests { #[test] fn path() { let seed = [0; 32]; - let xsk_m = ExtendedSpendingKey::master(&seed).unwrap(); + let xsk_m = ExtendedSpendingKey::master(&seed, ZIP32_ORCHARD_PERSONALIZATION).unwrap(); let xsk_5h = xsk_m.derive_child(ChildIndex::hardened(5)).unwrap(); assert!(bool::from( - ExtendedSpendingKey::from_path(&seed, &[ChildIndex::hardened(5)]) - .unwrap() - .ct_eq(&xsk_5h) + ExtendedSpendingKey::from_path( + &seed, + &[ChildIndex::hardened(5)], + ZIP32_ORCHARD_PERSONALIZATION + ) + .unwrap() + .ct_eq(&xsk_5h) )); let xsk_5h_7 = xsk_5h.derive_child(ChildIndex::hardened(7)).unwrap(); assert!(bool::from( ExtendedSpendingKey::from_path( &seed, - &[ChildIndex::hardened(5), ChildIndex::hardened(7)] + &[ChildIndex::hardened(5), ChildIndex::hardened(7)], + ZIP32_ORCHARD_PERSONALIZATION ) .unwrap() .ct_eq(&xsk_5h_7) diff --git a/tests/builder.rs b/tests/builder.rs index 8ce67e92a..56d2e5107 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -4,18 +4,25 @@ use orchard::{ builder::{Builder, BundleType}, bundle::{Authorized, Flags}, circuit::{ProvingKey, VerifyingKey}, + domain::OrchardDomain, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, - note::ExtractedNoteCommitment, - note_encryption::OrchardDomain, + note::{AssetBase, ExtractedNoteCommitment}, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, - Bundle, + Anchor, Bundle, Note, }; use rand::rngs::OsRng; -use zcash_note_encryption::try_note_decryption; +use zcash_note_encryption_zsa::try_note_decryption; -fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey) { - assert!(matches!(bundle.verify_proof(vk), Ok(()))); +pub fn verify_bundle( + bundle: &Bundle, + vk: &VerifyingKey, + verify_proof: bool, +) { + if verify_proof { + assert!(matches!(bundle.verify_proof(vk), Ok(()))); + } let sighash: [u8; 32] = bundle.commitment().into(); let bvk = bundle.binding_validating_key(); for action in bundle.actions() { @@ -27,34 +34,66 @@ fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey) { ); } -#[test] -fn bundle_chain() { +pub fn build_merkle_path(note: &Note) -> (MerklePath, Anchor) { + // Use the tree with a single leaf. + let cmx: ExtractedNoteCommitment = note.commitment().into(); + let leaf = MerkleHashOrchard::from_cmx(&cmx); + let mut tree = BridgeTree::::new(100); + tree.append(leaf); + let position = tree.mark().unwrap(); + let root = tree.root(0).unwrap(); + let auth_path = tree.witness(position, 0).unwrap(); + let merkle_path = MerklePath::from_parts( + u64::from(position).try_into().unwrap(), + auth_path[..].try_into().unwrap(), + ); + let anchor = root.into(); + assert_eq!(anchor, merkle_path.root(cmx)); + (merkle_path, anchor) +} + +trait BundleOrchardFlavor: OrchardFlavor { + const DEFAULT_BUNDLE_TYPE: BundleType; + const SPENDS_DISABLED_FLAGS: Flags; +} + +impl BundleOrchardFlavor for OrchardVanilla { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_VANILLA; + const SPENDS_DISABLED_FLAGS: Flags = Flags::SPENDS_DISABLED_WITHOUT_ZSA; +} + +impl BundleOrchardFlavor for OrchardZSA { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_ZSA; + const SPENDS_DISABLED_FLAGS: Flags = Flags::SPENDS_DISABLED_WITH_ZSA; +} + +fn bundle_chain() { let mut rng = OsRng; - let pk = ProvingKey::build(); - let vk = VerifyingKey::build(); + let pk = ProvingKey::build::(); + let vk = VerifyingKey::build::(); let sk = SpendingKey::from_bytes([0; 32]).unwrap(); let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); // Create a shielding bundle. - let shielding_bundle: Bundle<_, i64> = { + let shielding_bundle: Bundle<_, i64, FL> = { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); let mut builder = Builder::new( BundleType::Transactional { - flags: Flags::SPENDS_DISABLED, + flags: FL::SPENDS_DISABLED_FLAGS, bundle_required: false, }, anchor, ); let note_value = NoteValue::from_raw(5000); assert_eq!( - builder.add_output(None, recipient, note_value, None), + builder.add_output(None, recipient, note_value, AssetBase::native(), None), Ok(()) ); - let (unauthorized, bundle_meta) = builder.build(&mut rng).unwrap().unwrap(); + let (unauthorized, bundle_meta) = builder.build(&mut rng).unwrap(); assert_eq!( unauthorized @@ -74,42 +113,57 @@ fn bundle_chain() { }; // Verify the shielding bundle. - verify_bundle(&shielding_bundle, &vk); + verify_bundle(&shielding_bundle, &vk, true); - // Create a shielded bundle spending the previous output. - let shielded_bundle: Bundle<_, i64> = { + let note = { let ivk = PreparedIncomingViewingKey::new(&fvk.to_ivk(Scope::External)); - let (note, _, _) = shielding_bundle + shielding_bundle .actions() .iter() .find_map(|action| { let domain = OrchardDomain::for_action(action); try_note_decryption(&domain, &ivk, action) }) - .unwrap(); - - // Use the tree with a single leaf. - let cmx: ExtractedNoteCommitment = note.commitment().into(); - let leaf = MerkleHashOrchard::from_cmx(&cmx); - let mut tree = BridgeTree::::new(100); - tree.append(leaf); - let position = tree.mark().unwrap(); - let root = tree.root(0).unwrap(); - let auth_path = tree.witness(position, 0).unwrap(); - let merkle_path = MerklePath::from_parts( - u64::from(position).try_into().unwrap(), - auth_path[..].try_into().unwrap(), + .unwrap() + .0 + }; + + // Test that spend adding attempt fails when spends are disabled. + // Note: We do not need a separate positive test for spends enabled + // as the following code adds spends with spends enabled. + { + let (merkle_path, anchor) = build_merkle_path(¬e); + + let mut builder = Builder::new( + BundleType::Transactional { + // Intentionally testing with SPENDS_DISABLED_WITHOUT_ZSA as SPENDS_DISABLED_WITH_ZSA is already + // tested above (for OrchardZSA case). Both should work. + flags: Flags::SPENDS_DISABLED_WITHOUT_ZSA, + bundle_required: false, + }, + anchor, ); - let anchor = root.into(); - assert_eq!(anchor, merkle_path.root(cmx)); - let mut builder = Builder::new(BundleType::DEFAULT, anchor); + assert!(builder.add_spend(fvk.clone(), note, merkle_path).is_err()); + } + + // Create a shielded bundle spending the previous output. + let shielded_bundle: Bundle<_, i64, FL> = { + let (merkle_path, anchor) = build_merkle_path(¬e); + + let mut builder = Builder::new(FL::DEFAULT_BUNDLE_TYPE, anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( - builder.add_output(None, recipient, NoteValue::from_raw(5000), None), + builder.add_output( + None, + recipient, + NoteValue::from_raw(5000), + AssetBase::native(), + None + ), Ok(()) ); - let (unauthorized, _) = builder.build(&mut rng).unwrap().unwrap(); + let (unauthorized, _) = builder.build(&mut rng).unwrap(); let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(&pk, &mut rng).unwrap(); proven @@ -118,5 +172,15 @@ fn bundle_chain() { }; // Verify the shielded bundle. - verify_bundle(&shielded_bundle, &vk); + verify_bundle(&shielded_bundle, &vk, true); +} + +#[test] +fn bundle_chain_vanilla() { + bundle_chain::() +} + +#[test] +fn bundle_chain_zsa() { + bundle_chain::() } diff --git a/tests/issuance_global_state.rs b/tests/issuance_global_state.rs new file mode 100644 index 000000000..199138605 --- /dev/null +++ b/tests/issuance_global_state.rs @@ -0,0 +1,320 @@ +use std::collections::HashMap; + +use rand::{rngs::OsRng, RngCore}; + +use orchard::{ + asset_record::AssetRecord, + issuance::{ + verify_issue_bundle, + Error::{ + IssueActionPreviouslyFinalizedAssetBase, MissingReferenceNoteOnFirstIssuance, + ValueOverflow, + }, + IssueBundle, IssueInfo, Signed, + }, + keys::{FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey}, + note::{AssetBase, Nullifier}, + value::NoteValue, + Address, Note, +}; + +fn random_bytes(mut rng: OsRng) -> [u8; N] { + let mut bytes = [0; N]; + rng.fill_bytes(&mut bytes); + bytes +} + +#[derive(Clone)] +struct TestParams { + rng: OsRng, + isk: IssuanceAuthorizingKey, + ik: IssuanceValidatingKey, + recipient: Address, + sighash: [u8; 32], + first_nullifier: Nullifier, +} + +// For testing global state only - should not be used in an actual setting. +fn setup_params() -> TestParams { + use group::{ff::PrimeField, Curve, Group}; + use pasta_curves::{arithmetic::CurveAffine, pallas}; + + let rng = OsRng; + + let isk = IssuanceAuthorizingKey::from_bytes(random_bytes(rng)).unwrap(); + let ik: IssuanceValidatingKey = (&isk).into(); + + let fvk = FullViewingKey::from(&SpendingKey::from_bytes(random_bytes(rng)).unwrap()); + let recipient = fvk.address_at(0u32, Scope::External); + + let sighash = random_bytes(rng); + + // For testing purposes only: replicate the behavior of orchard's `Nullifier::dummy` + // and `extract_p` functions, which are marked as `pub(crate)` in orchard and are therefore + // not visible here. + let first_nullifier = { + let point = pallas::Point::random(rng); + + let base = point + .to_affine() + .coordinates() + .map(|c| *c.x()) + .unwrap_or_else(pallas::Base::zero); + + Nullifier::from_bytes(&base.to_repr()).unwrap() + }; + + TestParams { + rng, + isk, + ik, + recipient, + sighash, + first_nullifier, + } +} + +fn build_state_entry( + asset_base: &AssetBase, + amount: u64, + is_finalized: bool, + reference_note: &Note, +) -> (AssetBase, AssetRecord) { + ( + *asset_base, + AssetRecord::new(NoteValue::from_raw(amount), is_finalized, *reference_note), + ) +} + +#[derive(Clone)] +struct IssueTestNote { + asset_desc: Vec, + amount: u64, + is_finalized: bool, + first_issuance: bool, +} + +impl IssueTestNote { + fn new(asset_desc: &[u8], amount: u64, is_finalized: bool, first_issuance: bool) -> Self { + Self { + asset_desc: asset_desc.to_vec(), + amount, + is_finalized, + first_issuance, + } + } +} + +fn get_first_note(bundle: &IssueBundle, action_index: usize) -> &Note { + bundle.actions()[action_index].notes().first().unwrap() +} + +fn build_issue_bundle(params: &TestParams, data: &[IssueTestNote]) -> IssueBundle { + let TestParams { + rng, + ref isk, + ref ik, + recipient, + sighash, + ref first_nullifier, + } = *params; + + let IssueTestNote { + asset_desc, + amount, + is_finalized, + first_issuance, + } = data.first().unwrap().clone(); + + let (mut bundle, _) = IssueBundle::new( + ik.clone(), + asset_desc.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(amount), + }), + first_issuance, + rng, + ) + .unwrap(); + + if is_finalized { + bundle.finalize_action(&asset_desc).unwrap(); + } + + for IssueTestNote { + asset_desc, + amount, + is_finalized, + first_issuance, + } in data.iter().skip(1).cloned() + { + bundle + .add_recipient( + &asset_desc, + recipient, + NoteValue::from_raw(amount), + first_issuance, + rng, + ) + .unwrap(); + + if is_finalized { + bundle.finalize_action(&asset_desc).unwrap(); + } + } + + bundle + .update_rho(first_nullifier) + .prepare(sighash) + .sign(isk) + .unwrap() +} + +// Issuance workflow test: performs a series of bundle creations and verifications, +// with a global state simulation +#[test] +fn issue_bundle_verify_with_global_state() { + let params = setup_params(); + + let TestParams { ik, sighash, .. } = params.clone(); + + let asset1_desc = b"Verify with issued assets 1".to_vec(); + let asset2_desc = b"Verify with issued assets 2".to_vec(); + let asset3_desc = b"Verify with issued assets 3".to_vec(); + let asset4_desc = b"Verify with issued assets 4".to_vec(); + + let asset1_base = AssetBase::derive(&ik, &asset1_desc); + let asset2_base = AssetBase::derive(&ik, &asset2_desc); + let asset3_base = AssetBase::derive(&ik, &asset3_desc); + let asset4_base = AssetBase::derive(&ik, &asset4_desc); + + let mut global_state = HashMap::new(); + + // We'll issue and verify a series of bundles. For valid bundles, the global + // state is updated and must match the expected result. For invalid bundles, + // we check the expected error, leaving the state unchanged. + + // ** Bundle1 (valid) ** + + let bundle1 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset1_desc, 7, false, true), + IssueTestNote::new(&asset1_desc, 8, false, false), + IssueTestNote::new(&asset2_desc, 10, true, true), + IssueTestNote::new(&asset3_desc, 5, false, true), + ], + ); + + let expected_global_state1 = HashMap::from([ + build_state_entry(&asset1_base, 15, false, get_first_note(&bundle1, 0)), + build_state_entry(&asset2_base, 10, true, get_first_note(&bundle1, 1)), + build_state_entry(&asset3_base, 5, false, get_first_note(&bundle1, 2)), + ]); + + global_state.extend( + verify_issue_bundle(&bundle1, sighash, |asset| global_state.get(asset).cloned()).unwrap(), + ); + assert_eq!(global_state, expected_global_state1); + + // ** Bundle2 (valid) ** + + let bundle2 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset1_desc, 3, true, true), + IssueTestNote::new(&asset3_desc, 20, false, false), + ], + ); + + let expected_global_state2 = HashMap::from([ + build_state_entry(&asset1_base, 18, true, get_first_note(&bundle1, 0)), + build_state_entry(&asset2_base, 10, true, get_first_note(&bundle1, 1)), + build_state_entry(&asset3_base, 25, false, get_first_note(&bundle1, 2)), + ]); + + global_state.extend( + verify_issue_bundle(&bundle2, sighash, |asset| global_state.get(asset).cloned()).unwrap(), + ); + assert_eq!(global_state, expected_global_state2); + + // ** Bundle3 (invalid) ** + + let bundle3 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset1_desc, 3, false, true), + IssueTestNote::new(&asset3_desc, 20, false, false), + ], + ); + + let expected_global_state3 = expected_global_state2; + + assert_eq!( + verify_issue_bundle(&bundle3, sighash, |asset| global_state.get(asset).cloned()) + .unwrap_err(), + IssueActionPreviouslyFinalizedAssetBase, + ); + assert_eq!(global_state, expected_global_state3); + + // ** Bundle4 (invalid) ** + + let bundle4 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset3_desc, 50, true, true), + IssueTestNote::new(&asset4_desc, 77, false, false), + ], + ); + + let expected_global_state4 = expected_global_state3; + + assert_eq!( + verify_issue_bundle(&bundle4, sighash, |asset| global_state.get(asset).cloned()) + .unwrap_err(), + MissingReferenceNoteOnFirstIssuance, + ); + assert_eq!(global_state, expected_global_state4); + + // ** Bundle5 (invalid) ** + + let bundle5 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset3_desc, u64::MAX - 20, true, true), + IssueTestNote::new(&asset4_desc, 77, false, true), + ], + ); + + let expected_global_state5 = expected_global_state4; + + assert_eq!( + verify_issue_bundle(&bundle5, sighash, |asset| global_state.get(asset).cloned()) + .unwrap_err(), + ValueOverflow, + ); + assert_eq!(global_state, expected_global_state5); + + // ** Bundle6 (valid) ** + + let bundle6 = build_issue_bundle( + ¶ms, + &[ + IssueTestNote::new(&asset3_desc, 50, true, true), + IssueTestNote::new(&asset4_desc, 77, false, true), + ], + ); + + let expected_global_state6 = HashMap::from([ + build_state_entry(&asset1_base, 18, true, get_first_note(&bundle1, 0)), + build_state_entry(&asset2_base, 10, true, get_first_note(&bundle1, 1)), + build_state_entry(&asset3_base, 75, true, get_first_note(&bundle1, 2)), + build_state_entry(&asset4_base, 77, false, get_first_note(&bundle6, 1)), + ]); + + global_state.extend( + verify_issue_bundle(&bundle6, sighash, |asset| global_state.get(asset).cloned()).unwrap(), + ); + assert_eq!(global_state, expected_global_state6); +} diff --git a/tests/zsa.rs b/tests/zsa.rs new file mode 100644 index 000000000..337c6fbf8 --- /dev/null +++ b/tests/zsa.rs @@ -0,0 +1,589 @@ +mod builder; + +use crate::builder::verify_bundle; +use bridgetree::BridgeTree; +use incrementalmerkletree::Hashable; +use orchard::bundle::Authorized; +use orchard::issuance::{verify_issue_bundle, AwaitingNullifier, IssueBundle, IssueInfo, Signed}; +use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; +use orchard::note::{AssetBase, ExtractedNoteCommitment, Nullifier}; + +use orchard::tree::{MerkleHashOrchard, MerklePath}; +use orchard::{ + builder::{Builder, BundleType}, + circuit::{ProvingKey, VerifyingKey}, + domain::OrchardDomain, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + orchard_flavor::OrchardZSA, + value::NoteValue, + Address, Anchor, Bundle, Note, +}; +use rand::rngs::OsRng; +use zcash_note_encryption_zsa::try_note_decryption; + +#[derive(Debug)] +struct Keychain { + pk: ProvingKey, + vk: VerifyingKey, + sk: SpendingKey, + fvk: FullViewingKey, + isk: IssuanceAuthorizingKey, + ik: IssuanceValidatingKey, + recipient: Address, +} + +impl Keychain { + fn pk(&self) -> &ProvingKey { + &self.pk + } + fn sk(&self) -> &SpendingKey { + &self.sk + } + fn fvk(&self) -> &FullViewingKey { + &self.fvk + } + fn isk(&self) -> &IssuanceAuthorizingKey { + &self.isk + } + fn ik(&self) -> &IssuanceValidatingKey { + &self.ik + } +} + +fn prepare_keys() -> Keychain { + // FIXME: consider adding test for OrchardDomainVanilla as well + let pk = ProvingKey::build::(); + let vk = VerifyingKey::build::(); + + let sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + + let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); + let ik = IssuanceValidatingKey::from(&isk); + Keychain { + pk, + vk, + sk, + fvk, + isk, + ik, + recipient, + } +} + +fn sign_issue_bundle( + awaiting_nullifier_bundle: IssueBundle, + isk: &IssuanceAuthorizingKey, + first_nullifier: &Nullifier, +) -> IssueBundle { + let awaiting_sighash_bundle = awaiting_nullifier_bundle.update_rho(first_nullifier); + let sighash = awaiting_sighash_bundle.commitment().into(); + let prepared_bundle = awaiting_sighash_bundle.prepare(sighash); + prepared_bundle.sign(isk).unwrap() +} + +fn build_and_sign_bundle( + builder: Builder, + mut rng: OsRng, + pk: &ProvingKey, + sk: &SpendingKey, +) -> Bundle { + let unauthorized = builder.build(&mut rng).unwrap().0; + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); + proven + .apply_signatures(rng, sighash, &[SpendAuthorizingKey::from(sk)]) + .unwrap() +} + +pub fn build_merkle_path_with_two_leaves( + note1: &Note, + note2: &Note, +) -> (MerklePath, MerklePath, Anchor) { + let mut tree = BridgeTree::::new(100); + + // Add first leaf + let cmx1: ExtractedNoteCommitment = note1.commitment().into(); + let leaf1 = MerkleHashOrchard::from_cmx(&cmx1); + tree.append(leaf1); + let position1 = tree.mark().unwrap(); + + // Add second leaf + let cmx2: ExtractedNoteCommitment = note2.commitment().into(); + let leaf2 = MerkleHashOrchard::from_cmx(&cmx2); + tree.append(leaf2); + let position2 = tree.mark().unwrap(); + + let root = tree.root(0).unwrap(); + let anchor = root.into(); + + // Calculate first path + let auth_path1 = tree.witness(position1, 0).unwrap(); + let merkle_path1 = MerklePath::from_parts( + u64::from(position1).try_into().unwrap(), + auth_path1[..].try_into().unwrap(), + ); + + // Calculate second path + let auth_path2 = tree.witness(position2, 0).unwrap(); + let merkle_path2 = MerklePath::from_parts( + u64::from(position2).try_into().unwrap(), + auth_path2[..].try_into().unwrap(), + ); + + assert_eq!(anchor, merkle_path1.root(cmx1)); + assert_eq!(anchor, merkle_path2.root(cmx2)); + (merkle_path1, merkle_path2, anchor) +} + +fn issue_zsa_notes( + asset_descr: &[u8], + keys: &Keychain, + first_nullifier: &Nullifier, +) -> (Note, Note, Note) { + let mut rng = OsRng; + // Create a issuance bundle + let awaiting_nullifier_bundle_asset = IssueBundle::new( + keys.ik().clone(), + asset_descr.to_owned(), + Some(IssueInfo { + recipient: keys.recipient, + value: NoteValue::from_raw(40), + }), + true, + &mut rng, + ); + + assert!(awaiting_nullifier_bundle_asset.is_ok()); + + let (mut awaiting_nullifier_bundle, _) = awaiting_nullifier_bundle_asset.unwrap(); + + assert!(awaiting_nullifier_bundle + .add_recipient( + asset_descr, + keys.recipient, + NoteValue::from_raw(2), + false, + &mut rng, + ) + .is_ok()); + + let issue_bundle = sign_issue_bundle(awaiting_nullifier_bundle, keys.isk(), first_nullifier); + + // Take notes from first action + let notes = issue_bundle.get_all_notes(); + let reference_note = notes[0]; + let note1 = notes[1]; + let note2 = notes[2]; + + verify_reference_note( + reference_note, + AssetBase::derive(&keys.ik().clone(), asset_descr), + ); + + assert!(verify_issue_bundle(&issue_bundle, issue_bundle.commitment().into(), |_| None).is_ok()); + + (*reference_note, *note1, *note2) +} + +fn create_native_note(keys: &Keychain) -> Note { + let mut rng = OsRng; + + let shielding_bundle: Bundle<_, i64, OrchardZSA> = { + // Use the empty tree. + let anchor = MerkleHashOrchard::empty_root(32.into()).into(); + + let mut builder = Builder::new(BundleType::Coinbase, anchor); + assert_eq!( + builder.add_output( + None, + keys.recipient, + NoteValue::from_raw(100), + AssetBase::native(), + None + ), + Ok(()) + ); + let unauthorized = builder.build(&mut rng).unwrap().0; + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.create_proof(keys.pk(), &mut rng).unwrap(); + proven.apply_signatures(rng, sighash, &[]).unwrap() + }; + let ivk = keys.fvk().to_ivk(Scope::External); + let (native_note, _, _) = shielding_bundle + .actions() + .iter() + .find_map(|action| { + let domain = OrchardDomain::for_action(action); + try_note_decryption(&domain, &PreparedIncomingViewingKey::new(&ivk), action) + }) + .unwrap(); + + native_note +} + +struct TestSpendInfo { + note: Note, + merkle_path: MerklePath, +} + +impl TestSpendInfo { + fn merkle_path(&self) -> &MerklePath { + &self.merkle_path + } +} + +struct TestOutputInfo { + value: NoteValue, + asset: AssetBase, +} + +fn build_and_verify_bundle( + spends: Vec<&TestSpendInfo>, + outputs: Vec, + assets_to_burn: Vec<(AssetBase, NoteValue)>, + anchor: Anchor, + expected_num_actions: usize, + keys: &Keychain, +) -> Result<(), String> { + let rng = OsRng; + let shielded_bundle: Bundle<_, i64, OrchardZSA> = { + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); + + spends + .iter() + .try_for_each(|spend| { + builder.add_spend(keys.fvk().clone(), spend.note, spend.merkle_path().clone()) + }) + .map_err(|err| err.to_string())?; + outputs + .iter() + .try_for_each(|output| { + builder.add_output(None, keys.recipient, output.value, output.asset, None) + }) + .map_err(|err| err.to_string())?; + assets_to_burn + .into_iter() + .try_for_each(|(asset, value)| builder.add_burn(asset, value)) + .map_err(|err| err.to_string())?; + build_and_sign_bundle(builder, rng, keys.pk(), keys.sk()) + }; + + // Verify the shielded bundle, currently without the proof. + verify_bundle(&shielded_bundle, &keys.vk, true); + assert_eq!(shielded_bundle.actions().len(), expected_num_actions); + assert!(verify_unique_spent_nullifiers(&shielded_bundle)); + Ok(()) +} + +fn verify_unique_spent_nullifiers(bundle: &Bundle) -> bool { + let mut unique_nulifiers = Vec::new(); + let spent_nullifiers = bundle + .actions() + .iter() + .map(|action| *action.nullifier()) + .collect::>(); + spent_nullifiers.iter().enumerate().all(|(i, item)| { + unique_nulifiers.push(*item); + // Check if the item is already in the unique_nullifiers vector by checking that the first + // position of the item is equal to the current index i. + unique_nulifiers.iter().position(|x| x == item) == Some(i) + }) +} + +/// Validation for reference note +/// +/// The following checks are performed: +/// - the note value of the reference note is equal to 0 +/// - the asset of the reference note is equal to the provided asset +/// - the recipient of the reference note is equal to the reference recipient +fn verify_reference_note(note: &Note, asset: AssetBase) { + let reference_sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let reference_fvk = FullViewingKey::from(&reference_sk); + let reference_recipient = reference_fvk.address_at(0u32, Scope::External); + assert_eq!(note.value(), NoteValue::from_raw(0)); + assert_eq!(note.asset(), asset); + assert_eq!(note.recipient(), reference_recipient); +} + +/// Issue several ZSA and native notes and spend them in different combinations, e.g. split and join +#[test] +fn zsa_issue_and_transfer() { + // --------------------------- Setup ----------------------------------------- + + let keys = prepare_keys(); + let asset_descr = b"zsa_asset".to_vec(); + + let native_note = create_native_note(&keys); + + // Prepare ZSA + let (reference_note, zsa_note_1, zsa_note_2) = + issue_zsa_notes(&asset_descr, &keys, &native_note.nullifier(keys.fvk())); + verify_reference_note(&reference_note, zsa_note_1.asset()); + + let (merkle_path1, merkle_path2, anchor) = + build_merkle_path_with_two_leaves(&zsa_note_1, &zsa_note_2); + + let zsa_spend_1 = TestSpendInfo { + note: zsa_note_1, + merkle_path: merkle_path1, + }; + let zsa_spend_2 = TestSpendInfo { + note: zsa_note_2, + merkle_path: merkle_path2, + }; + + let (native_merkle_path_1, native_merkle_path_2, native_anchor) = + build_merkle_path_with_two_leaves(&native_note, &zsa_note_1); + let native_spend: TestSpendInfo = TestSpendInfo { + note: native_note, + merkle_path: native_merkle_path_1, + }; + let zsa_spend_with_native: TestSpendInfo = TestSpendInfo { + note: zsa_note_1, + merkle_path: native_merkle_path_2, + }; + + // --------------------------- Tests ----------------------------------------- + + // 1. Spend single ZSA note + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: zsa_spend_1.note.value(), + asset: zsa_spend_1.note.asset(), + }], + vec![], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 2. Split single ZSA note into 3 notes + let delta_1 = 2; // arbitrary number for value manipulation + let delta_2 = 5; // arbitrary number for value manipulation + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta_1 - delta_2), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_1), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_2), + asset: zsa_spend_1.note.asset(), + }, + ], + vec![], + anchor, + 3, + &keys, + ) + .unwrap(); + + // 3. Join 2 ZSA notes into a single note + build_and_verify_bundle( + vec![&zsa_spend_1, &zsa_spend_2], + vec![TestOutputInfo { + value: NoteValue::from_raw( + zsa_spend_1.note.value().inner() + zsa_spend_2.note.value().inner(), + ), + asset: zsa_spend_1.note.asset(), + }], + vec![], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 4. Take 2 ZSA notes and send them as 2 notes with different denomination + build_and_verify_bundle( + vec![&zsa_spend_1, &zsa_spend_2], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta_1), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_2.note.value().inner() + delta_1), + asset: zsa_spend_2.note.asset(), + }, + ], + vec![], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 5. Spend single ZSA note, mixed with native note (shielding) + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![ + TestOutputInfo { + value: zsa_spend_1.note.value(), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(100), + asset: AssetBase::native(), + }, + ], + vec![], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 6. Spend single ZSA note, mixed with native note (shielded to shielded) + build_and_verify_bundle( + vec![&zsa_spend_with_native, &native_spend], + vec![ + TestOutputInfo { + value: zsa_spend_1.note.value(), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(native_spend.note.value().inner() - delta_1 - delta_2), + asset: AssetBase::native(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_1), + asset: AssetBase::native(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_2), + asset: AssetBase::native(), + }, + ], + vec![], + native_anchor, + 4, + &keys, + ) + .unwrap(); + + // 7. Spend ZSA notes of different asset types + let (reference_note, zsa_note_t7, _) = + issue_zsa_notes(b"zsa_asset2", &keys, &native_note.nullifier(keys.fvk())); + verify_reference_note(&reference_note, zsa_note_t7.asset()); + let (merkle_path_t7_1, merkle_path_t7_2, anchor_t7) = + build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note_2); + let zsa_spend_t7_1: TestSpendInfo = TestSpendInfo { + note: zsa_note_t7, + merkle_path: merkle_path_t7_1, + }; + let zsa_spend_t7_2: TestSpendInfo = TestSpendInfo { + note: zsa_note_2, + merkle_path: merkle_path_t7_2, + }; + + build_and_verify_bundle( + vec![&zsa_spend_t7_1, &zsa_spend_t7_2], + vec![ + TestOutputInfo { + value: zsa_spend_t7_1.note.value(), + asset: zsa_spend_t7_1.note.asset(), + }, + TestOutputInfo { + value: zsa_spend_t7_2.note.value(), + asset: zsa_spend_t7_2.note.asset(), + }, + ], + vec![], + anchor_t7, + 2, + &keys, + ) + .unwrap(); + + // 8. Same but wrong denomination + let result = std::panic::catch_unwind(|| { + build_and_verify_bundle( + vec![&zsa_spend_t7_1, &zsa_spend_t7_2], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_t7_1.note.value().inner() + delta_1), + asset: zsa_spend_t7_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_t7_2.note.value().inner() - delta_1), + asset: zsa_spend_t7_2.note.asset(), + }, + ], + vec![], + anchor_t7, + 2, + &keys, + ) + .unwrap(); + }); + assert!(result.is_err()); + + // 9. Burn ZSA assets + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![], + vec![(zsa_spend_1.note.asset(), zsa_spend_1.note.value())], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 10. Burn a partial amount of the ZSA assets + let value_to_burn = 3; + let value_to_transfer = zsa_spend_1.note.value().inner() - value_to_burn; + + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: NoteValue::from_raw(value_to_transfer), + asset: zsa_spend_1.note.asset(), + }], + vec![(zsa_spend_1.note.asset(), NoteValue::from_raw(value_to_burn))], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 11. Try to burn native asset - should fail + let result = build_and_verify_bundle( + vec![&native_spend], + vec![], + vec![(AssetBase::native(), native_spend.note.value())], + native_anchor, + 2, + &keys, + ); + match result { + Ok(_) => panic!("Test should fail"), + Err(error) => assert_eq!(error, "Burning is only possible for non-native assets"), + } + + // 12. Try to burn zero value - should fail + let result = build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: zsa_spend_1.note.value(), + asset: zsa_spend_1.note.asset(), + }], + vec![(zsa_spend_1.note.asset(), NoteValue::from_raw(0))], + anchor, + 2, + &keys, + ); + match result { + Ok(_) => panic!("Test should fail"), + Err(error) => assert_eq!(error, "Burning is not possible for zero values"), + } +}