commit 7c7b705c654fcf02692c3dc0cc486949e1a54bed
parent 05d9fa00c2041c37298ca80e8f429037902fca65
Author: Joris Hartog <jorishartog@hotmail.com>
Date: Mon, 14 Sep 2026 00:17:28 +0200
test(protocol): add quantum audit coverage
Diffstat:
16 files changed, 293 insertions(+), 19 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,6 +1,7 @@
/target
/fuzz/target
/fuzz/artifacts
+/fuzz/coverage
/.docker-build
/.iuna
/e2e/.runtime
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -10,6 +10,7 @@ from the Git history and Conventional Commit titles by `deployment.sh`.
- expose complete peer handshake details in the P2P interface
- add dormant transaction-v2 encoding and activation gating
- verify both components of dormant hybrid transaction authorizations
+- add pinned ML-DSA audit vectors and transaction-v2 fuzz coverage
## [0.4.32] - 2026-09-13
diff --git a/README.md b/README.md
@@ -110,8 +110,11 @@ By default, deployment audits all three Rust lockfiles, enforces the dependency
source/license policy, runs the regular unit tests, verifies that the fuzz
targets compile against their locked dependencies, and runs the extended
adversarial, fuzz, post-height-1000 six-node E2E, and release-property suites.
-Release hosts therefore need `cargo-audit`, `jq`, and Docker Compose in addition
-to the pinned Rust 1.88 toolchain. To
+Release hosts therefore need `cargo-audit`, `jq`, Docker Compose, the nightly Rust toolchain, and
+exactly `cargo-fuzz 0.13.2` in addition to the pinned Rust 1.88 toolchain. Coverage-guided fuzzing
+runs for 60 seconds per target and 15 seconds for the VDF target by default; override these with
+`IUNA_FUZZ_SECONDS` and `IUNA_VDF_FUZZ_SECONDS`. Corpus discoveries and crash artifacts are retained
+under `release-evidence/fuzz/`. To
explicitly skip the long-running suites:
```sh
diff --git a/deployment.sh b/deployment.sh
@@ -5,6 +5,7 @@ cd "$(dirname "${BASH_SOURCE[0]}")"
RELEASE_ROLLBACK_ARMED=false
RELEASE_START_HEAD=""
+CARGO_FUZZ_VERSION="0.13.2"
RELEASE_VERSION_FILES=(
CHANGELOG.md
Cargo.toml
@@ -45,6 +46,33 @@ require_command() {
command -v "$command_name" >/dev/null 2>&1 || die "missing required command: ${command_name}"
}
+require_cargo_fuzz() {
+ require_command cargo-fuzz
+ require_command rustup
+
+ local installed_version
+ installed_version="$(cargo fuzz --version)"
+ [ "$installed_version" = "cargo-fuzz ${CARGO_FUZZ_VERSION}" ] || \
+ die "cargo-fuzz ${CARGO_FUZZ_VERSION} is required, found ${installed_version}"
+ rustup run nightly rustc --version >/dev/null 2>&1 || \
+ die "a nightly Rust toolchain is required for coverage-guided fuzzing"
+}
+
+run_fuzz_campaign() {
+ local target="$1"
+ local seconds="$2"
+ local evidence_dir="$3"
+ local corpus_dir="${evidence_dir}/corpus/${target}"
+ local artifact_dir="${evidence_dir}/artifacts/${target}"
+
+ mkdir -p "$corpus_dir" "$artifact_dir"
+ cp -R "fuzz/corpus/${target}/." "$corpus_dir/"
+ cargo +nightly fuzz run "$target" "$corpus_dir" -- \
+ -max_total_time="$seconds" \
+ -timeout=10 \
+ -artifact_prefix="${artifact_dir}/"
+}
+
docker_native_linux_platform() {
local architecture
@@ -204,20 +232,24 @@ run_release_tests() {
return 0
fi
- local fuzz_runs="${IUNA_FUZZ_RUNS:-256}"
- local vdf_fuzz_runs="${IUNA_VDF_FUZZ_RUNS:-16}"
- validate_positive_integer IUNA_FUZZ_RUNS "$fuzz_runs"
- validate_positive_integer IUNA_VDF_FUZZ_RUNS "$vdf_fuzz_runs"
+ local fuzz_seconds="${IUNA_FUZZ_SECONDS:-60}"
+ local vdf_fuzz_seconds="${IUNA_VDF_FUZZ_SECONDS:-15}"
+ validate_positive_integer IUNA_FUZZ_SECONDS "$fuzz_seconds"
+ validate_positive_integer IUNA_VDF_FUZZ_SECONDS "$vdf_fuzz_seconds"
+ require_cargo_fuzz
+
+ local release_evidence_dir="${IUNA_RELEASE_EVIDENCE_DIR:-release-evidence}"
+ local fuzz_evidence_dir="${release_evidence_dir}/fuzz"
cargo test --locked --release --lib domain::adversarial_tests:: -- --ignored
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin p2p_envelope -- -runs="$fuzz_runs" fuzz/corpus/p2p_envelope
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin compact_snapshot -- -runs="$fuzz_runs" fuzz/corpus/compact_snapshot
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin domain_json -- -runs="$fuzz_runs" fuzz/corpus/domain_json
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin stratum_request -- -runs="$fuzz_runs" fuzz/corpus/stratum_request
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin wallet_config -- -runs="$fuzz_runs" fuzz/corpus/wallet_config
- cargo run --locked --manifest-path fuzz/Cargo.toml --bin vdf_proof -- -runs="$vdf_fuzz_runs" fuzz/corpus/vdf_proof
+ run_fuzz_campaign p2p_envelope "$fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign compact_snapshot "$fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign domain_json "$fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign stratum_request "$fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign wallet_config "$fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign vdf_proof "$vdf_fuzz_seconds" "$fuzz_evidence_dir"
+ run_fuzz_campaign transaction_v2 "$fuzz_seconds" "$fuzz_evidence_dir"
cargo test --locked --release --features e2e --test properties -- --ignored
- local release_evidence_dir="${IUNA_RELEASE_EVIDENCE_DIR:-release-evidence}"
./e2e/iuna_e2e.py test post-activation --build --evidence-dir "$release_evidence_dir"
}
diff --git a/docs/quantum-migration.md b/docs/quantum-migration.md
@@ -114,6 +114,13 @@ has not been independently audited, so an independent review and an explicit bac
decision remain prerequisites before activation. No transaction-v2 gossip capability is
advertised yet.
+The verification tests include a small audit corpus pinned to exact NIST ACVP-Server and C2SP
+Wycheproof commits and file hashes. It covers a valid NIST signature, Wycheproof's repeated-hint
+regression, and a valid signature at the ML-DSA-44 norm boundary. A dedicated fuzz target exercises
+both the transaction-v2 decoder and arbitrary ML-DSA-44 verification inputs; it remains part of the
+release's time-bounded, coverage-guided `cargo fuzz` gate while transaction v2 is dormant. Seed
+corpora, newly discovered coverage inputs, and crash artifacts are retained as release evidence.
+
## Other trust boundaries
- P2P node IDs need versioned, algorithm-tagged proofs independent of wallet activation.
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
@@ -49,3 +49,9 @@ name = "vdf_proof"
path = "fuzz_targets/vdf_proof.rs"
test = false
doc = false
+
+[[bin]]
+name = "transaction_v2"
+path = "fuzz_targets/transaction_v2.rs"
+test = false
+doc = false
diff --git a/fuzz/README.md b/fuzz/README.md
@@ -2,10 +2,11 @@
These targets exercise external input boundaries and persistence decoders.
-Install `cargo-fuzz` once:
+Install the release-pinned `cargo-fuzz` version once. Building the helper may use a newer stable
+toolchain without changing Iuna's Rust 1.88 build contract:
```sh
-cargo install cargo-fuzz
+cargo +1.98.1 install cargo-fuzz --version 0.13.2 --locked
```
Run a target:
@@ -17,9 +18,20 @@ cargo fuzz run domain_json
cargo fuzz run stratum_request
cargo fuzz run wallet_config
cargo fuzz run vdf_proof
+cargo fuzz run transaction_v2
```
-Short smoke run without installing `cargo-fuzz`:
+`cargo fuzz` requires a nightly Rust toolchain and adds sanitizer and coverage instrumentation.
+For a bounded run, use for example:
+
+```sh
+cargo +nightly fuzz run transaction_v2 -- -max_total_time=300
+```
+
+The release gate also applies a 10-second per-input timeout so hangs are retained
+as actionable fuzzing failures alongside crashes.
+
+Short, uninstrumented crash smoke run without installing `cargo-fuzz`:
```sh
cargo run --manifest-path fuzz/Cargo.toml --bin p2p_envelope -- -runs=1 fuzz/corpus/p2p_envelope
@@ -28,6 +40,7 @@ cargo run --manifest-path fuzz/Cargo.toml --bin domain_json -- -runs=1 fuzz/corp
cargo run --manifest-path fuzz/Cargo.toml --bin stratum_request -- -runs=1 fuzz/corpus/stratum_request
cargo run --manifest-path fuzz/Cargo.toml --bin wallet_config -- -runs=1 fuzz/corpus/wallet_config
cargo run --manifest-path fuzz/Cargo.toml --bin vdf_proof -- -runs=1 fuzz/corpus/vdf_proof
+cargo run --manifest-path fuzz/Cargo.toml --bin transaction_v2 -- -runs=1 fuzz/corpus/transaction_v2
```
Targets intentionally accept malformed input. A parse error is fine; panics,
diff --git a/fuzz/corpus/transaction_v2/valid_hybrid_transfer.hex b/fuzz/corpus/transaction_v2/valid_hybrid_transfer.hex
@@ -0,0 +1 @@
+hex:49554e412d54582d563200020000000c69756e612d76322d746573742222222222222222222222222222222222222222222222222222222222222222010000000111111111111111111111111111111111111111111111111111111111111111110000000701f8c30468e6b2099cfd4717151d08fbce96f9521e2a68561f7a6c3eb7d78be3f60000000101333333333333333333333333333333333333333333333333333333333333333300000000000000050000000000000001000000010200000540ea4a6c63e29c520abef5507b132ec5f9954776aebebe7b92421eea691446d22c61907fb0bdd3bbc3433851a933515bb97cbba4a91550418d99f04f90243f82c8e1085c1a05fe0c04cc2ac4759ba358e7467cb386b13318e15ba49b67a6fbffa704c6b107f77c4386706f755808f51e02e6ef1dccb385ac3f809dd3420d77832099238ed4666042572473c53abc149798f0bf5ef9d325d1c0088b2b201770e669da085cbc96c7d6dad2cfb934aaf765bfd4e6500e19b8b18f7d4fd8cecac039cb22133c4d0498f955739e1c9169401f46d7dc75b7dd6ce3e0ec217de775cb10d3b1c4f8e591ae2ce17d4fc677476d34a70e12c3f6253ce85f1aecc087e7a8cd9ed641ac022203ea6e5138ba89e4b4dd9f6e5154ac3004b4c44cc7f317ce39800447072cf3106c29e7de42cd0ad50202d329cf9ccc85290c5798cc619ce132e23f9000ecdb59dc581e4fbbaaedd8893f74aa1d25a715e41260192d5105f1268b8aa5bdb071cd9a5c78661a7996a3ac2fd421f01c1964568320dd65a30b035b9dcfb7b1f8116e2596b0827cddeae055ea03df5569419b31787f01be81036b7cbd3a5375f64359bacfc20b19d603cc4507bd62c563883fa09dfbcfc7f0e7db1ea6ca1e4b4ae9eb6476699406803f504777221665f8195788b9954cbc25d216b87c782e96bc4f13b0e8305fb76fe5dce572f4ebf72041c0661fc9a117e254465269005e3cc75f807e019001fe6bfa194799c3e76a8487239dc926a2458b53212626c60810f4f08bc7d2daf17060495c1853db1f9eff9a47692240ce7c6cdeb320787c87f354031988475c64df16dd2f81cdc6a9fbfc96ab98598e9b4797c168a01fb9f2c805192fff941046cc60cecbf03eae42b648ca7fedd98a3115466f3b5d41756a7bd626887fcca0d2a1f164aba6bbbc99d502b9cb3624030c22a95fd9dd32eeb50230f41a4c118aa5232d7d4f2ddb1019422a998b47cd780c8c3485c406ffa5be1367adeeb4e6e04dbb5329a64ce8c9ff51bae5eac9e36c43ebc7f55d6cf30cbb8c8ff93b19cbfe07eb2b83b708977f01dca642d3c33b3814a7d3129353a8ef8773e47e684c0a60c85937ab6cae98ce735e11a13f64ae0e3295b55766d2b91c621c98c9e79a3deb81ed652b3e30b664fc3de7d7507dcbbb1a97ccf8e34b931e22fb0a414e5a8f55efeb2033027a7601e75059e0626ffb0718c9834a8bf4c9522e45da893250de3a5ab02f83c273afd631f3d34e7c3ebe3ea0c30f87db66cdafde936bab8609e7e09addc2288750c4aa1e9521d1cc8ec40c15b78a19487ee32ca2e38b5db02168426cecc00b79b39b96332a084ff6ddd4b6ec16c0adddcc681e28684d5d66ad30897e77054a7808933206e3939217c429dd64a5fb6ff52cc8124950b9ef7b0ef3b0b4711a7b535bc69bd2d96f22d956394d9e53b4ba2ae9b10864094d77b122022c9290dc6eb02fe38f04fb64c47c32bc98370dc98eb610a26b3c8c48f09bf6e70761fe2a188ebbe11c7e93d72729731d8743213f4c5c7982707644ad975a1b04465b64d0e92f2f9ba93c2a9d66e0a647e3ed9988a5e42efbfbdad0044972b90a5f519c756e2e88be4498c2452b2aedb70701d9179b95a763879b0ed8d60987cc1a4d922a2d815b3b940b26a0526a7daa0304bdc68d67ce13ef6cef7be46d003a4f7e93f9987e9412f63eb81b1fc1737ea3a16b6a97c9c3a15da5f77b2f438c2016ec7fd0e561540e6a9620b7f83eab9b70b34757bc214fa27c568b93830d690fe0f78ec0e1f458189ccbb5277705a956e58486be5231f9a91a3a9ba19719f3c4d3a559ab6f2a6deb95854c1d5487e8e476d58e2c76e21eb070bc99c5fb0450cb2e430915d1a98d48f2a23211e08eb3bb5b9c8430ec4cde1b0e000009b4611f07fed31940b5e3c64c6b5b085b2b7b0a4b88b5f04cf0f333968fce2d91493fabc751bcf2d3bb122037807271ca6caf7659e0b91c693212bdfb203d5df60df54d310ce128f82de130b8a7b486a27c308390f9b53b9bfd609afd97e0d11a943147e0cd2bbe939db6b69ef58a89737cface942386635e938d1806c5b076d99302dfb600b8afeb10007462e15b9908a84f572f7578a5c9709f0291fe2222b6172703e30f887919a91c1794234097e2cfc145afa7e3bc0383e11b1abab4e64e3f5b2fce8ea92ac3bfb9ddc6e4f99f660a606812d75907fc49bc30583270cb53024e77bff861d4726e4c8133765bcb147959bd90e3fa18cdcedf00d1a9795a40c2ad9e0033d19cd257b4e3b8432fbcf7c84905dc903e502ffa1ac04afc7a1eb19a5f34863b72373fa3402568d4ca615762b5a6c5db9786a192a18e0247aafa2e2b7c20e61360e63520ae00ade83641ed87c0e505c0ea4ec62ca60c606a05cdc5a80aaac06488919f7085de3e3e091c310b4b2f27d59f2c91920735acd7b467eda1431334374ea6a49e7b894d69a935f55d02c08b2fe57e7f1c2d842183d61d3a65a380e1e7f74c144ab6cb435e49ae2ca61afd9f741a9594bdd027703197eeab41d5fec5ec395fd27d3d38685b1a6f39cc1f03bfa2eb2fa489b966b96c8f54a9434a1ec9e7ebef0756ec046c96786d062741d2b0bd1ba3094aeaa2b2a3b32cfeaa079d77b540540fd70c001712d3813c99ea701631866ae33de63e2ee6da24efde3e9777001ec67f7bdf9d6544129bc67b2580c83aae26a6fed7af030ad2cfd0cce04022509d715f68895e1c2ae96fa421537db9661a62b5d8a66d0b9ea71f4eb82d4088fc256860fe470188ea345cc027c847d284a67f1daea110eeddcd0e29a131f1e2ea0b30236610c24f599c73d39aa28395eb445c559221a41647e59d5020c0ab08c8d825e52164a4ed18dc49c3c8d5facc0495ce7f984f1495a67268fa82eb0e039bf29337cc9b475ec585707a97222dfaec9cec468510a43da1d719e2c04668ecb67d69e7a2022e4385747f9aca93341938bb1091dab04b2a78d839b338bfd1070d8379bbdc79f354b081da1ed33f4229f268b1a832a335deb7e347236eb7c0ab061244cc1fce7f6fb50848a67148be210961b1f231b5c87e882bea83db3da0179a57518f5d8af097aee23a9beddd3422e717bbbaeff704e774ae5fdbff49cc0a9e581507042e2e4486b80a461e61d93d989e6ca25014099567d280ef944ee6cd4140f4f88ade67f7dbb6b8a47829e782a943db850da0099552f70cd1145bbdffaec8f7fc930ef8f843883404fcaadd3ca7a73d2a2225edb81cbeb5780c8332668c61df986c49410230de0d7ca1db6a1f6f396adf032749fa3ffc388f537e6b9e13cc9f2c6db24a600e4e7897706c541e018ada21400c6be56b20b555aeb1d5a394a00767731446631f920ec5ee879f6df60cf28fe8518001c1dc6b5f3120f92ac142f6e95f8908bf46039b17fbcc6a39f753e8184cecde98c49de5898d545a36cc2903e05d6fad9dbd0f711a7736627f0d92c2dae233d6043212ad8f146ba07c573967ac4534ad27597e7c06847b819e854dbfdf215b08a40d4d37ed61f87e86f28ad32cfb82f5d6eebe0dc1441ee884d4e2ae746f2c4fe15cd4a31b8337e233b94b071ddcffe851410b00cf8e877ab4e38384cce500ab899b13cf228cde114a4f350a7495bf972648329635f471d9f1040590fc261bc7ae9d41b00a2ca0fae871acbebac32ad3702ad990ce6c4c4255db4883fbdc810cc08ddc4c7d01ff7e6cb80f484ee561eed3506a4b779af5663c316bd40ea48bec7838b7f908054197181daf6e59cc1996c4ef8cb6e215ed965ea28e64b8edd75705b314f941f281a0f1804b76c0d6c626a11841a3e7fc2b583a7df74b7be284d00721c27e05b45e645b90f546cccf3b32c3d7b63bc14cfdd71966c765b221913348ad000b610cf0456ae4297569433def53b4951720d1b882b717ebc552d26351a01fc3539d63b9d25d25d64013e4647995718a5083b69089ecfea1ff5061a8a8f2a78792f28e6211f9812bec6f61cc0ecd11d8428db9c40863828f72afc60c6985fb8ece7e801ece28098bf93cd790054207bf699bf7941a8eb14447ea90267bee3b57e1e6caedf8df64bcb74642df5c9f9033236d391642edfbf7d213aa5510f61175ef73ea2704e938ce8ad1a9cc84850d73f60873deb461d9884023949b6513399f8d85bef74cd180b5f2df67eee35e2749bac81ce37482878ce70e139c79d01c3ba9e93f7e26f77c98ac20e2cc96a285193721a47b352bb2d568e095b1c40c1fe5a6ea22aada74d96ccae7edfac7a646d5661bfdeecdb37112858c54879b571489e2ba7b0a2b765e74453463a04e1c0e742272c0335f58a238b82cc0194afa7625489bf09b443f718bc3bdb2e389f7aaca2fa1f2782e33d1ed34d962a9549abbd860d6a864d8114f682e2a7aa7aab1767b3027a49a1af0dc13afa838f5364b891839249f5c234052d362ac0085615e616297cd7e89cb765e238f2ba5bb0146d45884368df12fa1afaf2468f2445759a39736e2fae9916d823260f230a89e1415fa5e3a5c2a74e09a16db6788a8eba156bd1ec6b1d767bfd870d1c12b68d9426d8cd7a2b97215904d5309c39ca72293523aab49dddb5a13f2d6be7858c52733509fe12bd4df1b05439bbb36b81b7a75e2955ceedcf1dedbad3bc58bc075c06f2e5b21390fc6ee21047d5ae84ceb6c53e6944c352db53523d00d2f43930364a4e85da5170ba91f3fffbc626f380de28e55d7f4dac65f7bd8f9af46d8784b7031afafb3227c651b0b7c50535114f11e9e512a2a94c75c118afbd3146e444c30ab701da0395deefd3b18602db875218d7e394413e54a24a1bb7e13eed81229be795f57a58ff11b0b82c880e3862ac7ba73214e1226f57f0ab16eefce72938f7475fedfa4b06c155baec39da995131536add82ba950294087d428e110edcc3ccfb4ecbd010a052f2fc86ad745e99088ea6832ef159aaa0a38b6d46b4fb7a1c42682a2091c08cda9de9110cade2a8a356f75dcd8a68673c13fa6f0416725728f7b91cb82236c1f8e693d3629780cdc6a3248e565991ca769cf3d613c8b3fc502c9d1534dcf85c8d31b1ab0c4aeba44e7dc03b7a08284b9656997ee7eb22101cb0c2476a4ea428ad7926d41b1de36c9b18764026744803cd919b42caf00bc4e95b28b6d8b726c549c7c834bfb1eb46c054b49b0a14d9bdb19e4ce2153e8245f791c3b97285f8520c288f889f31d82ca0581233ccbab2fb25a0b235cffcb027cccb31f8159836d88ec967b0b71a4811f62b64fc542a6d90cce9d1dfacbce9e0c23ff32a73a865c8c032d42485271778487acaecfe8f2fc072d375154565b686d7fb2d1d5f30e41434a5b62666c8f92bcc9cdd5e2e3f6f7141c292c2f3334393a3c42434a4c4f5a9ba3aab3b9d5eb000000000000000000000f1d2f46
diff --git a/fuzz/corpus/transaction_v2/valid_mine.hex b/fuzz/corpus/transaction_v2/valid_mine.hex
@@ -0,0 +1 @@
+hex:49554e412d54582d563200020000000c69756e612d76322d746573742222222222222222222222222222222222222222222222222222222222222222030003030303030303030303030303030303030303030303030303030303030303030404040404040404040404040404040404040404040404040404040404040404000000000000000500000000000000060000000700080808080808080808080808080808080808080808080808080808080808080800000000
diff --git a/fuzz/corpus/transaction_v2/valid_ml_dsa44.hex b/fuzz/corpus/transaction_v2/valid_ml_dsa44.hex
@@ -0,0 +1 @@
+hex:db9ac67708f2ba0fac1f92bd802f9be89ecab966feef59872a1a9ac90b1111170a561290ae86b13968f2506023c014ba09fa449a26e4e9d35595e73986506cc8790e4d07a94d6c736f7ae78cc5e3e3cf025ce06a09252bef97fe92e94cbd107b1844d1a7c690d88bff9e9336f8f58e0bd5ee384de9c7ffbb149a6fcd87c77288601d8843e28e0c7a60149d02ebc57b183c39888d98b61cd8ad48135ddb8a1666743bb689f44c1a92d52017b6a8fa493eeb839dffb086a9a6c399b194a52f0e4164c96ff8a2a54337de24350a866b5fe4195257778e72511221778f1eae5fa93ed3532f696b9b0767aded85f62ea311027c7f5fc4182dcd2864b1c26bd6dcf72ebdedf70471327be0ea1c2ae53e46489c6dbefa512a78fdd7be0ad3ada16a7f7b1ece49817b44868a2cc234bfdba556c32cc92ec2c5e8a5d206f2e4ee372d41681e67d1b7e7b0061870c57f600fafca85f98aed8ce4ba76bba961f9ed56e563220d3ced853b6b28e7527da0e0912bc932a23c8bab811429bbb4d49b2770bcda44abb932b11c0a5866409fce39fed2b459c86c8f6e1ab0aefc5879503f4b21a49b4b2de6760c9b6aaf041144a656a26af39f4578e1d482ddc1360ef751d9784b860ec373d415360fe99f32e126a2ac1243430e8bed1bc90b19b3d219c2712edcf81c44b4331f6421088e662b695e1fd8fa5091f616ab60af70f159b63368f1ac60d77b279ed47ef7f24ec2044bb6c2bc76d933ecd568f7e663392afc1d335abac6c03670adf87747dde90052f5cd45f7d30f43a4dc3c500ceb658fce235c171240baca1b5a14733d774b9416c540f53eb83481afc98344b12a4309e6222b08d978430467497010314c6f6b8caf65361c216106395275a67d7500dbc120f7918c6f8db7aa63fa965b4a22c70dc88f727d768ce2bfc7597fd470184e1c59a6b2e1204cc8c3d052c594d5771e0ccc8cfb191f47038b1c0672f07caf4747562d3d76a9816fb1def1391cf0f05fcdbf2a0eb6c21ac24b26e74ee403133e80a79313ddb02c1fa386c6dd1d420195343e3a104aff6d60887f7304fa9e3bb59bb55f820dd85b1445c54e9a38dc1c7f3b88eb36a9f48d13455e51c934825ff3cd8bedb2b5422344120399eef83a360b83440ebdd8ea6e01c95159e3735bb4408500caa785ca4049891c7331c4ea31ad9060ece768fd339e6904f88e27bad3b28845687be2cc9314f300fda56fe3ff2508e54c59123b068f86fe00213d5af8da1b1735423ed688f097c306dbc121b81f532fcaf872d9f80596642295d6e4bead478644081618ab903b39e9b5e7cc0b5f2742d8337b18d4ad4788db7443e946cafc1762a5da84070e8c2fd86d6c633f0b44ee234ba11b9e1440c94a08d0437015279690405353059020fd2f58f15dab18754177244adfb81ceab79c7840bf3884a3d364afc8c453a425fd8c5378eaa7445f8c6256bfbd03a66c53e8cf27e2c52f14ef3294afe79cda408f5dff933ca0211a78a4e3be3d9a932558ed71ed19bbb57f87937fa3d4a78128491ff096a261045bdd186325c42caa8c7564195a4d2499a1c17d21a52d1aacd221d9c8a1866963a20390f2fd43dcf56b308a1c01c38091fd3e04c12b695de497d48bcc268d50cb0bed793b8e6937e8d533afd568521f1c9377a3804d38e785674d7ce868d289938e33dda6edc76d25b15fcb38852b7803cfe62f08d9fbd070957c4e6f134973964c9dc009985c8501e7d8f72e7ec285d5289fdd07f64d62acaa9737b039efa7a9d1d175577c6bcf9dddcf692877af38e75263bebe2453155be61f0723c274388a532abe29dd7023e327085f4c9dda41839b7b3357ab9ddfe343f52cd8b02b7e88bdb005c9a7388c7b79f2eed8e5bfeba82fd0af881dbf2903ec43d62e2fbe1bcf93932dc1f23dcd5c37fcd983e04c39798d94fceaf467145c1725980a53a8c0a91f50850789642b8eaf7ad51d07f61eece822a8746eab811c02d0ab6b6ac7a253a3a7e9cbf0db24bea21aa4af4a81bd9217982be2de73b05e2cad8a333e07d1db4b9bea89188cf4e352ee6b7358d4f36a0172e475707231c95fa9efe7c0be8a3c3f6d69eb02f758e58d2d45127237d0a6a297c385cd3fd1275e12159a9fe308736b43a6b07f73150be6188eca2737fe13075f06a07d89246842cb20914802758e23c02d6574f90367df7d03eeba9854c9c7a3ab50a590bf9560558013581826b9d2f580864157004ca797141f2ee2d5c53dfcb54486aca1e45c00bac15427c808f07e26dc58d0179e335fc03c3481fc150ec60e51b6dc1aedbbf063a36d6281a056b3e8ad5c5e05e7231712e5f8f5b3a143010859b4e0f22a1017ed9650e10d6c6ed48bc46a3db05cc14a492c7cb20b3645c6cac987ceaf6a1b76de185ed957778536ad3c4e01976f2e94fc72d2d4600081c3ecf8df85bce36ed432a8bf56ac376363576defb499dff634217b04cd6d88577da65acb831680bb6a71c7f7e6aaca1aa6bae12d64fe1c6ee6c612d2bcea338c8cf853135242711520efb8c2170cdfe5f058649b6c91231fd42144bbf1a726ef9ca7934fc301c48274e994cd011f1c42d24d90441ca07df7696b9dca3e0594cc1b120616d9739af9b6b56792caeff19e3a24b7e8a85184b4d37bbbf1379af62963ca7a35cd4bd707bb590ae078cc7e37c77b4f60a10bf61a49843a2d7eafb611371bd0a689fc19a195ebbedb608692e16cc7bf958b2c701a111d65f32176181dd1086df6e96678027388e5861402f76259b7f0429e2b910b615c4ba0d9be48ea809acb4ec632f22802078aa09ec62cb1a41caba18d63edc26f8e2397f2baced378b55fa4947eab200b5ed6e084728f9c8b142e4c5e36d9612b1e8e47da60bf3147c8be7b09fb231d6333aee7ce8aad378a7b093d50103b5b76488e5f19859acd5f2709bc5a38e621ac11139209c97713f490f25d0d162e2607e5b6644293b546e7b2662930dd25fa3217c8047e7685e1f89aa76badfb11b01b654caca3bd3c3446c0aa142e7b3dbc469e4dfa1b175ecd3c63fc205bf03bacd97e3b20d89c0ae1e1f653ef0a3660281f9a0834fc1ce1b948d1186a0a2045439a196d82e8b7a9fbcb8c39913e81b177a9fefb9e1187686c3f5608f8636760d87490b0e7c17ddb87d45ba2edc2fd98808bdbd88de4483b96668ce7032d2ca085dab535cd2ec5998d7a2f0aaf2aa10a0f28773562f7a5d3e70a51ff43240492ec75825de0393d49e6bd03ad2f3b8ca501695f78d898bbf47b3a686d4d82d842ee727f05bed87c2cd8c4fd83304e19f2282d003aa0eb00c2c164594a6d90263754904ec2eef3e04bfc91263afd651bcfc24c73fca0d15adbb4e539a5e6c29db82e1f04546c6b93b83f458d1dd46c3f5e06b35c5e68645652f9512320d295ab864c96b8b9adc6dac6f5571912109c7dd6a8cde991124a6b223456913a3bd2ec4fd53f6edd9fa9dad4ced1013cdee1b9549a02d92068c715f4dfee8b5f4e409a9c8f7ef2643c64d466e176e6b6c61fe3e57f901d410d5d29d25f73a92ee57d2420ca2a628db8bcf940ca0a77c03be87e50dad4cbdb76f33bcc3957fb1e105f0a1ec6a6a823bda552b70d1fa9440d6aa428e170ffc9c16cf621058c6fc2aed2f40d67daaea9124f1ca26862089a18fbdf174255ae3ed0fad143a4fdeb80450b93443317b9cf592cf5a58da86de34c17845ec86a51037acbb5858b5ad6aba69efa83cac149ac9ec9a344fd152abfe1a04de7ebcf6fb0ba7530db08499765b7d5471f101d75a3ffc276009accc5ccc18583c921515e018cfc50c3adabbbf50347f864b1110a0032be50bdd75edd36c9339a9a43575e6147b6ac2740364e6866f0939399ae28e5faa7eba4e7bb852070b5611200f486a23ad245cec296d90cea001d87adfe119e9ca7aaed3ed99a9efa007e5068345adb680c2653e3b90edef518bae3bbb22e67867aa6117aaf833497d7eb3d0f93056bef6a6cd1118b5994a7b7b8f5199ff8461f00173ce254efe9222ef3cc15d4fe5f6b845bb0841dfeb8625792fd310a5d3fd136f28e303009e3132d47eb5a5367a712e34ba0dde4418fa9b606ab07b972fd0ef074e3f0f5a623c5a563135b3df0b6c3cd2ff33401dfcb914da724126340a171332730755bb2831975a721f1a9da0c89d88ea10ff7ccffb98259273f64c39f8308c2ddd876f320436e4ed572601f2d3c4a79477949bedce0660e7dd66705ebf1177e3744a824876a0a0222af69da59ea510910aeabdc5b3674337771114c47d9641aed3a4927ae517f16d7195a962c9c97c31d6519d8456a089eb96e3ad88b3c32fb927285c2fd37e042e83fe3b853e65a00540002f2d65a25e6b23a623ddb009e71ed99e3d76b5ab22bf61005378a109f738ab8f93216b4267941c54db49b8c64252a966dce1753efe2a50c91e57723584a08e7404ae6836c59da97fdc8d3aabcbba08145a16641c60891b360d1105161701d2042708767b83b1f5961e1eb123e2095adf8620c3e92db92877b06d3f86b881cfd170aae23e6dc4f7e0b4e367a61f5a764c69cfeaf8f92bac2b5ae0972c3cf0df0c00d1a0bc0bd441ff98f7a21b2e24e7c9e65c49a4aede9c35638ad02ac08097a7854df30bf0bc79eeb98348fa467f299f84818374930171b56aaf9f5d017bec3dbc6feff268174a4d6ca77eb5d3662b7dd8dc0aa58998ee371e0cf6fba03b131a2161a457bec7253dca23cdddea6a4384150481a9eb9fc79fbc6845dac0dbfbb376f2f5eba1d77a9635a902495d14f6550cbf26f4b42804bcb53d14b8c94e13e9cf9567cecbce3898fdbcd8fb71147005cbebd42ed15407f58925d4291021beb9e4d15105f3806d51c2bb2c4624824a2b5218bcd7ce5abe9989d8e4b0c9ee3aa8309bb73e676ee3b3c703be0e699417bff5363b4c0b505d8dc622f886afca74775e72e6eccef9e6ad22f166c3b48e57fe95a6320c10ae5ce1dd9cc948215672a3d4cde80704ec6c009e2aed6c4f0c1c7ac8e534a20d700f1201ba2ea63304e073bccf033f47da0175f870fd48a88b47760c22e5603d7f3fa0f928d5b968116cb86fe156913561145b7af61e6b686de2d124331e52cf64393951a687f830464b50e71295a97ab059c545a310a9659d7f22c8f114efd09141c1e20263a50939ba0a8b3cacbfa0f1d212731494e5b73757ea5b6b7bfe0f8fc073f4856656e849dabadd4eaf4f6031114262f3474758491b6bcbfd1d6d8eceff100000000000000000000000000102230434800000000000000000000000000000000000000000000000000000000000000
diff --git a/fuzz/fuzz_targets/transaction_v2.rs b/fuzz/fuzz_targets/transaction_v2.rs
@@ -0,0 +1,53 @@
+#![no_main]
+
+use iuna::domain::{TransactionV2, fuzz_verify_ml_dsa44};
+use libfuzzer_sys::fuzz_target;
+
+const PUBLIC_KEY_BYTES: usize = 1_312;
+const SIGNATURE_BYTES: usize = 2_420;
+const MAX_INPUT_BYTES: usize = 2 * 1024 * 1024;
+
+fuzz_target!(|data: &[u8]| {
+ if data.len() > MAX_INPUT_BYTES {
+ return;
+ }
+
+ exercise(data);
+ if let Some(hex) = data.strip_prefix(b"hex:") {
+ if let Some(decoded) = decode_hex(hex) {
+ exercise(&decoded);
+ }
+ }
+});
+
+fn exercise(data: &[u8]) {
+ if let Ok((domain, transaction)) = TransactionV2::decode(data) {
+ let _ = transaction.verify_hybrid_authorizations(&domain);
+ let _ = transaction.encode(&domain);
+ }
+
+ if let Some((public_key, rest)) = data.split_at_checked(PUBLIC_KEY_BYTES)
+ && let Some((signature, payload)) = rest.split_at_checked(SIGNATURE_BYTES)
+ {
+ fuzz_verify_ml_dsa44(public_key, payload, signature);
+ }
+}
+
+fn decode_hex(encoded: &[u8]) -> Option<Vec<u8>> {
+ if encoded.len() % 2 != 0 || encoded.len() / 2 > MAX_INPUT_BYTES {
+ return None;
+ }
+ encoded
+ .chunks_exact(2)
+ .map(|pair| Some(decode_nibble(pair[0])? << 4 | decode_nibble(pair[1])?))
+ .collect()
+}
+
+fn decode_nibble(byte: u8) -> Option<u8> {
+ match byte {
+ b'0'..=b'9' => Some(byte - b'0'),
+ b'a'..=b'f' => Some(byte - b'a' + 10),
+ b'A'..=b'F' => Some(byte - b'A' + 10),
+ _ => None,
+ }
+}
diff --git a/src/domain.rs b/src/domain.rs
@@ -88,6 +88,17 @@ pub use signature::{ProtocolPublicKey, ProtocolSignature, SignatureScheme};
pub(crate) use signature::{
ed25519_public_key, sign_ed25519, validate_ed25519_public_key, verify_ed25519, verify_ml_dsa44,
};
+
+#[cfg(feature = "fuzzing")]
+pub fn fuzz_verify_ml_dsa44(public_key: &[u8], payload: &[u8], signature: &[u8]) {
+ let Ok(public_key) = <&[u8; 1_312]>::try_from(public_key) else {
+ return;
+ };
+ let Ok(signature) = <&[u8; 2_420]>::try_from(signature) else {
+ return;
+ };
+ let _ = verify_ml_dsa44(public_key, payload, signature, "fuzz input");
+}
pub use stratum::{
STRATUM_EXTRANONCE1_HEX, STRATUM_EXTRANONCE2_SIZE, StratumMineShare, StratumMineTemplate,
pack_stratum_nonce,
diff --git a/src/domain/signature.rs b/src/domain/signature.rs
@@ -186,12 +186,22 @@ pub(crate) fn verify_ml_dsa44(
signature: &[u8; 2_420],
label: &str,
) -> Result<()> {
+ verify_ml_dsa44_with_context(public_key, payload, &[], signature, label)
+}
+
+fn verify_ml_dsa44_with_context(
+ public_key: &[u8; 1_312],
+ payload: &[u8],
+ context: &[u8],
+ signature: &[u8; 2_420],
+ label: &str,
+) -> Result<()> {
let encoded_public_key = EncodedVerifyingKey::<MlDsa44>::try_from(public_key.as_slice())
.with_context(|| format!("invalid {label} ML-DSA-44 public key length"))?;
let public_key = MlDsaVerifyingKey::<MlDsa44>::decode(&encoded_public_key);
let signature = MlDsaSignature::<MlDsa44>::try_from(signature.as_slice())
.with_context(|| format!("invalid {label} ML-DSA-44 signature encoding"))?;
- if !public_key.verify_with_context(payload, &[], &signature) {
+ if !public_key.verify_with_context(payload, context, &signature) {
bail!("{label} ML-DSA-44 signature is invalid");
}
Ok(())
@@ -199,10 +209,30 @@ pub(crate) fn verify_ml_dsa44(
#[cfg(test)]
mod tests {
+ use serde::Deserialize;
+
use super::{
ProtocolPublicKey, ProtocolSignature, SignatureScheme, ed25519_public_key, sign_ed25519,
- verify_ed25519,
+ verify_ed25519, verify_ml_dsa44_with_context,
};
+ use crate::domain::hex::decode_hex;
+
+ #[derive(Deserialize)]
+ struct MlDsaAuditFile {
+ vectors: Vec<MlDsaAuditVector>,
+ }
+
+ #[derive(Deserialize)]
+ struct MlDsaAuditVector {
+ source: String,
+ tc_id: u64,
+ comment: String,
+ expected_valid: bool,
+ public_key: String,
+ message: String,
+ context: String,
+ signature: String,
+ }
#[test]
fn signature_scheme_ids_and_sizes_are_stable() {
@@ -237,6 +267,36 @@ mod tests {
}
#[test]
+ fn ml_dsa44_matches_pinned_nist_and_wycheproof_vectors() {
+ let audit: MlDsaAuditFile =
+ serde_json::from_str(include_str!("../../tests/vectors/ml_dsa44_audit.json")).unwrap();
+
+ for vector in audit.vectors {
+ let public_key: [u8; 1_312] =
+ decode_hex(&vector.public_key).unwrap().try_into().unwrap();
+ let message = decode_hex(&vector.message).unwrap();
+ let context = decode_hex(&vector.context).unwrap();
+ let signature: [u8; 2_420] = decode_hex(&vector.signature).unwrap().try_into().unwrap();
+ let result = verify_ml_dsa44_with_context(
+ &public_key,
+ &message,
+ &context,
+ &signature,
+ "audit vector",
+ );
+
+ assert_eq!(
+ result.is_ok(),
+ vector.expected_valid,
+ "{} tcId {}: {}",
+ vector.source,
+ vector.tc_id,
+ vector.comment
+ );
+ }
+ }
+
+ #[test]
fn algorithm_tagged_material_roundtrips_and_rejects_malformed_lengths() {
let key = ProtocolPublicKey::new(SignatureScheme::MlDsa44, vec![5; 1_312]).unwrap();
let signature =
diff --git a/src/domain/transaction_v2.rs b/src/domain/transaction_v2.rs
@@ -692,7 +692,7 @@ mod tests {
use ml_dsa::{Keypair, MlDsa44, Seed, SigningKey as MlDsaSigningKey};
use super::*;
- use crate::domain::hex::hex_encode;
+ use crate::domain::hex::{decode_hex, hex_encode};
fn domain() -> TransactionV2Domain {
TransactionV2Domain::new("iuna-v2-test", [0x22; 32]).unwrap()
@@ -862,6 +862,18 @@ mod tests {
}
#[test]
+ fn transaction_v2_fuzz_corpus_contains_valid_decoder_and_verifier_seeds() {
+ for seed in [
+ include_str!("../../fuzz/corpus/transaction_v2/valid_mine.hex"),
+ include_str!("../../fuzz/corpus/transaction_v2/valid_hybrid_transfer.hex"),
+ ] {
+ let encoded = decode_hex(seed.trim().strip_prefix("hex:").unwrap()).unwrap();
+ let (domain, transaction) = TransactionV2::decode(&encoded).unwrap();
+ transaction.verify_hybrid_authorizations(&domain).unwrap();
+ }
+ }
+
+ #[test]
fn transaction_id_commits_to_authorization_bytes() {
let first = TransactionV2::Mine {
recipient: VersionedAddress {
diff --git a/tests/vectors/README.md b/tests/vectors/README.md
@@ -0,0 +1,23 @@
+# Cryptographic audit vectors
+
+`ml_dsa44_audit.json` is a curated subset of two upstream ML-DSA-44 verification corpora. The
+source commit, path, and SHA-256 digest of each complete upstream JSON file are recorded inside the
+fixture so an auditor can reproduce the selection without trusting this repository.
+
+Included cases:
+
+- NIST ACVP `tcId 11`: valid pure ML-DSA-44 signature with an external context;
+- Project Wycheproof `tcId 18`: invalid signature with a repeated hint index, the regression case
+ for CVE-2026-24850 / GHSA-5x2r-hc65-25f9;
+- Project Wycheproof `tcId 56`: valid signature immediately below the ML-DSA-44 `z` norm limit.
+
+The full upstream files are deliberately not vendored: together they exceed 5 MB. This small set is
+a permanent integration regression suite, not evidence that the upstream implementation itself has
+been comprehensively audited. Run it with:
+
+```sh
+cargo test ml_dsa44_matches_pinned_nist_and_wycheproof_vectors --lib
+```
+
+NIST ACVP material is published by the United States government. Project Wycheproof test vectors
+are Apache-2.0 licensed.
diff --git a/tests/vectors/ml_dsa44_audit.json b/tests/vectors/ml_dsa44_audit.json
@@ -0,0 +1,49 @@
+{
+ "schema": 1,
+ "sources": [
+ {
+ "name": "NIST ACVP-Server ML-DSA-sigVer-FIPS204",
+ "commit": "975de31eb83d87039ec88934fdc47d8c312b892d",
+ "path": "gen-val/json-files/ML-DSA-sigVer-FIPS204/internalProjection.json",
+ "sha256": "47cdd6314c7f746d02421ffcba89d4dbc7bb875ac49e07a029fdfc26fba55437"
+ },
+ {
+ "name": "C2SP Project Wycheproof ML-DSA-44",
+ "commit": "3fa63dd0344abb611f1fb1d77e119938603ea230",
+ "path": "testvectors_v1/mldsa_44_verify_test.json",
+ "sha256": "0ca1b5df4575263e29b31fae7569a3da41df9a3b6fee56720a992d0cd1153b68"
+ }
+ ],
+ "vectors": [
+ {
+ "source": "nist-acvp",
+ "tc_id": 11,
+ "comment": "valid signature and message - signature should verify successfully",
+ "expected_valid": true,
+ "public_key": "3AAFE3B287818A44346F2642700693490A8F2C5CC6A89853FC78F7A4A73EDB8D44AA62836269B171BEBD6F1CCB788E7E22BCA0B23C0F3367EE8740955A766FB8E483C8E1503A14F82A692DB06C70F2E88C22E1F634130EDE552EC493CA99B16AA272E43DEDFA52108461A8D119D11DF7361FB27B3FFE8CA92661F0446D643539443B945EB24F06CD348DA6072A1D1687D6F627133BA861EAEF0F93442763AA88E0F76F291CCDD0646DD5AFFEA38311BD5C2161EF3B5BACCBF275A98425AFA5644D78E57A618799E1A6ED59E11B18BF179BDBCBA4011C9F651F1C20A403FFAD97556190B449414B538C39234D874A1FDCF8BC27CE999C6F520EBF79FF9473C31169EEA0CEE82BA1B0151F2BC8CD898EEC51C5D359C120E7C4CBC1EACD085CF916973C95CDA2B0536E302DCCF0BDBFE150AD89259DE8255273C31D8E7CE86E8E79E89760CC22BE8C3D11C1CBC557902B2D7C4E12202F9B99BFF729E96AD5E71EEAA1B0E8D1333BCA71AB82AC9213F4EA4510D9A81F88AAF7D60441CC39DD7DFF68F17CCA4EDA4314F027AAE5BFB785F961BD7D9C4833A9CF513A3E1083C726F68ECECBC30F6B260D1B3480CF966D05FEF71507899FEA90088AD2022917B8115623E70B8AB44C73F9374D8FA6AEFA3AB3871E1D5BAFAFD4B2E49E72155E6C680EECDF6F6CB27E7D7715B2653BF08712765E65398FE207B37EBDFB7480A9F5CD698F4214214D1B4886EDA099B23E129E75FAB7EC797B7A62290AA3B2239C531508568C18C488657402AAB6AC2B7FC2678B67DD8C0122D2E4C915984C1AD29E8E5B7DEBD2A934F79888FDEA65D0EDBA03352E5CEF08BD0A09DC0282FF5D99C38C77FFFECA8B3F4196B5B691ED04903C717F3346A67F2325204735B26133129BE25DEBAB8E1E8DE1B47D2C0CA221C63B55D4CCE7F29915C16C53D6260258CF6977A233F77A500525AA79B0E8E8536D61CFF39919DE08CA191205E00102D1EC838179A96B9390A0868648812328C46F3863CCC16D9BC761EBB3493E7D54A4AEF5172550D9A6D5026018F47A0C3A6D9F822C5C1940B93041B2E1FA0AD87DEFAFBD64BBDCA6726424C39E7BFEC35454C212B809F629FB1F1F43108692AB5779C9E0B6DB1219638F6B446DB2FA5B3BDF423FDF329AA975BF2641B003EB83450559609859933FFB4CE0CC10075C8AE780D19644B68BD857500FDD40899255628EE03CF6F1367E37F584F78821D890870331E07570976CECFED143FA83606936715190B7FADF60371E4A92F6E4AF228EF060D292480300C6A9DFF734E444FE0139AAD4B483C4D1BFECBD0630A4D2743B99AC013340984FE29F5EFC1AD47765C16D87CBD5C0CD16A982449B6D919F2D0C834CE5763B9CDB24CC8BC9CD388F44DBE57E111067FC9BBDBAEA64AC44F95CF1E81B57B6CBB4CDC6003628B7768DAA36770B68F48DA94CBD8A221464467C092457E9A84E6D7882C8743FA972184537195970F659DD85B95B3DA32433FF248993727466BCC16E1527AA03B296DF8CF84010C92A25832C8F4762BF95C3D1A17881809C208BB05364935EED72F7AA013F7F4816E7CB21FE47DBE5E992809438D49814373259B9097FA420F8761175F23C195FE14D1B9B352609CC21D8E93E6D4F98008295B66FBA955A9790D4063A3FCF84FA6E7D4CB172F096E86424F8B11C36BCE327BDB22A061F0828C3E550560E7CEF8298C0CBD3A524996D48EE47F5CB86B7334B76CCDFCBBCA7DC37891060E455831305EA4D534B5814EE953B52D05269449D139FEE3F6D7500A08CCCDFC6136CBF82ADC6E0174BCA750600FA1C65C8EA5A51CC63844881A2290C354FFF0636C68DB2EBAC7B798F",
+ "message": "A1993D2461B99EFEEAEC415E9692A3C8BF19FCA8CBA4D46B889B1E522DE3E6437D93DE2B86ADAC239156E580BCDB6399064B7B87ADA0337FC4C3D10DDC2F54CF6CFD39FA2BAA133BA0AA48FF24992E59A9FA8182B35241B68D09D59AE84DCDD9560919EB340C9487CD2FDAEE57C1899A5DB95AAA08AAD985E96E06BF31E16A7A989FC0AE338C1303A58A2C8DD82A2594C9067B52C7667916B84C7848103911FABDB2187C5653A0D90C221182C191D261B617F943DB272CB11C1701D4662025B60CEE1FAA8BDBACC34A577AF418952EB920DE6836F01EE9DC5CA4580216EB3087162917F04BF2401F4DE962C4048856741A17BF96A73CE024DF6B9CCCFBF9ADAC1C7E7D6E0948D1E0751072D042C847F87053FCC3984C06949820381DD3B52FC0BAA48D4B81C7C816DB57E3ADD1784417886F812BB96751A9CAFF36D15EAC3858BD444887E0CF68F27EB62AE9F5D093CEF297CA0B0DED04032C6D1BEAB947CC0641D87E644737AF527A8F18BE6A7D16E5E9F0182BB379313CA990BF8F21E381977495670CB67DBE0BC27D843F29AD93EBFD3DCD3BDE409BA8E534E2064372CFFFCE426CFD691322B72CF76C4E2216718B960201F1E250DAE192D020D934EB032ECBA6559B3929EEFE2EB08CB9222E79050E17F146A09AA524DDA62657125167B8B08E7C9B1C7FA28748A28C8874B887B928322B9CA3B3BC4742711ADCB036A1BB380171A9E7A13839B394FA5DE2E796F882D78EB40CA0B92237643D54B8561C42006F700BB00991B6E7373C5DD6F4AC7FC6D232CC79A12A",
+ "context": "11326798703CDF88575C20BEEE8738E3D893138EAE44BDBAD3ADA7E1E947F6EC33A7593E4A66E0D78E4774C02042003350ED53EF751F7A6A70B2FF51136DD0CC1D4101EFBA88D02C8288AE29AE2D6CD2FFBB4EB913132E359714C61B93635F3C7023EE",
+ "signature": "7EFCA85402EDF73AA27FCB944668B7F4E1CEA5A3110CEFE5A637BEDD478C47454F59555B98B8717B623C282125185645EA3012AE5182FEA26B286C78089B298379FA5849D19FB0BD5B9D00A99636F4B6748F5DD6B7BC1126878B597CFDED3A81547C1A09FD062FE79BC67F335B283C0160FC181E80997B0C972DBE4FF6CBAE636BA85E6D629B76A044A347E1DDCCA5D900405CED8C52C836DEC000A56AC628A5C6083D127D0E92D4D7A09178687492F58D6ACA296B60E12545DB8D335225BA98DCC4B50F305C2ADEA76F7A0BCF6F7CEE64398720215B92EE1C4D7FB2D38A1CBAF02559A4373ADB64EFE51C13AA8FA008D2C16B565457BB0999B1807745CD918779EDA1C8E66AC856CBA85BF18E0905C3C297E9C29E63ACEC66588D52847E3184E88929E4BB178A66DCA6B2E702D5E0F72E88E017BC92DD66D479339382448A2E3C5B4C97D662608738963D9AF1DC2FF16014FAFB0944AC22AA88E65BC1E99DB3F428D8DAF2E15B1C10EBD6FC3CAA827F1CFF7CF96588D2D1E299F88B44D75F2AB4FECBF55FF8FAB0CABDB1F83D48D7174588660C1C1DC34B1CBBF8A3BF0776AB81800882C6F3A9E82D1494448167ED07FCFC4BEA9BDD25390D21EA3B2AC42BD93FB6191C87A81EDBF258651E0896DC74316A6EFE1695D10C676AE5683F7E28DFCB290CB820E4A90F88F93ECF5894CA8F7A057AFCF56F4884617CEFE2398BADF34DA13006B62A0B682E13929FFD0263946FBB922722CB37B2E3D8200A53755DCF1DCA6E65F8874D007D290D618DE35A850DC107C24B7C4C2927C547E12FB1BBEB6B6E89F1B2E18C28816FB60B98D7B5D54A9AF566AA41B4A8A3601877DCA4D6A7E862E66FCEB81559328F1DB487B94942ADA9EB6BC67B8DFCD938B8BD8B67B8024796E0F5DDBB3714D96025A14FF6B497FF98852F65F7F85E4C3683C2A2DEB0917076C0238CE027C6032A28E5D7A78EFAF02CECF27F79EAFF96BBFA7A9055CC2E8B4EE463B8426B40E28473D2385679B563F2D51FB4DA3207E02DAC1D3A9245ED68C0890B22542A54D4BCA564F15B4F8910558BD219F997495AB4035BB7F6444BD7F5251BEA840583CF9E9DF341E21780C943A0E9E89085FF15B6F5C1D4AAFAAB42109E593AF08AD81DA4D520E6707986F4B7D370ED038FB15E9E22C750DCBA965C4E9BA00E3F5E5E4F1FB8B7F949C7522477206EE6239C69DED0BC8389E7517222C88DDDC8D8C566FEB02626E6E2606ADA1118979C7F0A99A6C58B1B4E6F2F5E9A78EED712E68053313B6430D4893B3A2DFBC37FF27B16F37963B87B8BB824A44F4783615916B7890F2DA8D64D1FEF24D3F33A2C4A36058E83334F090F7562F292447EFC233F3D60A0492283C11EC547A22AC0FEBB1A8CE6C5EC43A6A68CF9F53189B55292C0521274323FAC673E165578263DAA89E3F8DEBF8A47E9CC4A824CFA6B7FC4171FFFFB252414FECE5C76A4A3F22F0112865373CCAFC93AAA239E54BC29E00F4E933591D851D574A945DC7EB9CA1F2F1C62D426940486DEB4D310EFF135A16973FC30265817A94F1B647D5B590D3B4C8709ACD31EB7D394DBB78E4227310E98229CED5D490826BE8C4DA2D45A2A6174DD2516E83DCE543BD0C00EF54E9E43D65F628F629427D6BAA3778987CADD72C1603EEE5590560A6511C17727D7BEEDA7AB47F78984791472E4BBAF9B2A101FBB28FEE1059465D5E09ED663F3E5963A52FA162BD9E798CCDF78758BC284CF4B044796BFB6719A10D1F2CF4B01EC56D3785A4A75D8FEED35AB67F68915A9F94715A971FD1CED568EC97CA8A35AF9B9F9AED305A7AABACCEE3DFFBF8666EFF46044E4758ED8A4FFAF5152AF4501981FF1ABAB062C2940DF52D54B481E9BE993E8177B8C047E17ABE6F46030FE105567CE0D7D48F6B863636597AE9D782D0850EEE9E7E78EF226C2DF5347DAC74EC99C3A683BC322775AA769CF9B598C5112B0560B8E4E30C55F573FAFE1C1D80E55EBD8665EA0EB292F3BB942E5779C71C79973D5D1FD8A9762DF6F7F601B7729849468CE3B0B1564325812D9EE4A520857530FDEC2C5C4BFEB375FDE35842BF75AD2750A816368100F626B0F61F7D74D0D1B86F97E1A8C9224DD0EB07F1B9374950EB6475C85C28218851D3EB5D69AE6A1CD948A898EAE4BAF128E0FAC3F2CF496B8D223FCBEAC4C53B9CB9D681BA235A42DD0FF8541B4E73D69077F42CF6D795AAF6509288A9EA06EF7D03EFD170C863F2C7AC54B42E331E035AFBE276BE21A51438412C31F612F40D514611B805722DF4AD220B6E9F40F090B741D50884BDFE9886400EC5948C433BC2638902698ADA54BB33BC46D0521F8E8D9649422805F1E26140D9A9D808911C322CA64CB70F8784079A7B4A278306C3C78EFFA385E6ED544FC4AE3688E85A0FC5715C6B077EC1F85AF9266146989DE1E47297448CD2474407FD20C64EC2A838D48381AF62E372A92EF669C9E223DE5BB98FC1EA3423A9E8F1A4A6469AEA5FA7628A2E4B64A1B3F16493DBB33CC37E3E49063403DF2A9D92E675F7F16E50F6200418A6941F6302B0D2063ACFC1C8DC8FFD1F8AE041AA4F5A3339083480C197F0EBBFE1708836CCC27AEEC15F3FA1406BACDB7609E475AA8757D160B3AB7C0D1F4C527127424C6DF4AD10E82A5CB8C23C36CA5537E698AF19C2A424D3B5E2EB88DB2B434D576DA0DD783E1152E170F26DE39046B216A14B55E313D26E605E28F2CBFB6BA2EFFE102B17D8B86377E1AD06F3561A1152DBA8E8B95A986D414487407CF64C2AB5BB43A3CF7E97118385EA45713FF0D66FE8F50DF8014B5E2B920FEA8C04CD7E6215E0842B69CB9E398F2E5A48093CE20EEB6570D8483E0C84F54E00DC8CC5BFD0AE5F2CA8B150184D8B098012B05F7EA1B78D14F76F8CFF29A78AA82C2DA43305F7C2AF0D09314CD34C4DAB4AA77BB6E928BDAE99DC6DB2DF7C1FE7E3042575C1F72777ED5E95E539E85B57A590A68A61C5B1C1DD8482DCE87708F2C88A70EDC62AAB0825EE16D2FF3E5BC45ABB742C4700B4C1F863D33DDC7DD34CD2AB33A7D6B02642808531B95135768F1811F5C6D7D0A5B6F43359B1C4FC3F2B6C3D98DFD172C959AD250FBCB081E979A4B6387099FB3F5C4A0869A890DF90C4691705CD649D24558E746D792A5A7D08CA3D9988D5244CF5132795D12F1452C325AC74F1EC458E83B3FA49881F0A1481BA33163D5CDA4CED8DA8968CF4AE8EF73E41A94F2E8825BCDD3F8C9915D21E533AFAAB3DFBC5072D005531CF038B68F04F1C8EC84B43D063E8BE811C61BD4DC9BCFE10C9F78E80002043C47575E627897A3BBBCC7CCDFE1E3E7FE09131C25292D4668797B8E9CAEB6DAE8F9FDFF1728363A40425F6EB0BEECEFF2FB191E262D2F4A738F9096989CB9BCD9DFFAFB00000000000000000014273547"
+ },
+ {
+ "source": "wycheproof",
+ "tc_id": 18,
+ "comment": "signature with a repeated hint",
+ "expected_valid": false,
+ "public_key": "db9ac67708f2ba0fac1f92bd802f9be89ecab966feef59872a1a9ac90b1111170a561290ae86b13968f2506023c014ba09fa449a26e4e9d35595e73986506cc8790e4d07a94d6c736f7ae78cc5e3e3cf025ce06a09252bef97fe92e94cbd107b1844d1a7c690d88bff9e9336f8f58e0bd5ee384de9c7ffbb149a6fcd87c77288601d8843e28e0c7a60149d02ebc57b183c39888d98b61cd8ad48135ddb8a1666743bb689f44c1a92d52017b6a8fa493eeb839dffb086a9a6c399b194a52f0e4164c96ff8a2a54337de24350a866b5fe4195257778e72511221778f1eae5fa93ed3532f696b9b0767aded85f62ea311027c7f5fc4182dcd2864b1c26bd6dcf72ebdedf70471327be0ea1c2ae53e46489c6dbefa512a78fdd7be0ad3ada16a7f7b1ece49817b44868a2cc234bfdba556c32cc92ec2c5e8a5d206f2e4ee372d41681e67d1b7e7b0061870c57f600fafca85f98aed8ce4ba76bba961f9ed56e563220d3ced853b6b28e7527da0e0912bc932a23c8bab811429bbb4d49b2770bcda44abb932b11c0a5866409fce39fed2b459c86c8f6e1ab0aefc5879503f4b21a49b4b2de6760c9b6aaf041144a656a26af39f4578e1d482ddc1360ef751d9784b860ec373d415360fe99f32e126a2ac1243430e8bed1bc90b19b3d219c2712edcf81c44b4331f6421088e662b695e1fd8fa5091f616ab60af70f159b63368f1ac60d77b279ed47ef7f24ec2044bb6c2bc76d933ecd568f7e663392afc1d335abac6c03670adf87747dde90052f5cd45f7d30f43a4dc3c500ceb658fce235c171240baca1b5a14733d774b9416c540f53eb83481afc98344b12a4309e6222b08d978430467497010314c6f6b8caf65361c216106395275a67d7500dbc120f7918c6f8db7aa63fa965b4a22c70dc88f727d768ce2bfc7597fd470184e1c59a6b2e1204cc8c3d052c594d5771e0ccc8cfb191f47038b1c0672f07caf4747562d3d76a9816fb1def1391cf0f05fcdbf2a0eb6c21ac24b26e74ee403133e80a79313ddb02c1fa386c6dd1d420195343e3a104aff6d60887f7304fa9e3bb59bb55f820dd85b1445c54e9a38dc1c7f3b88eb36a9f48d13455e51c934825ff3cd8bedb2b5422344120399eef83a360b83440ebdd8ea6e01c95159e3735bb4408500caa785ca4049891c7331c4ea31ad9060ece768fd339e6904f88e27bad3b28845687be2cc9314f300fda56fe3ff2508e54c59123b068f86fe00213d5af8da1b1735423ed688f097c306dbc121b81f532fcaf872d9f80596642295d6e4bead478644081618ab903b39e9b5e7cc0b5f2742d8337b18d4ad4788db7443e946cafc1762a5da84070e8c2fd86d6c633f0b44ee234ba11b9e1440c94a08d0437015279690405353059020fd2f58f15dab18754177244adfb81ceab79c7840bf3884a3d364afc8c453a425fd8c5378eaa7445f8c6256bfbd03a66c53e8cf27e2c52f14ef3294afe79cda408f5dff933ca0211a78a4e3be3d9a932558ed71ed19bbb57f87937fa3d4a78128491ff096a261045bdd186325c42caa8c7564195a4d2499a1c17d21a52d1aacd221d9c8a1866963a20390f2fd43dcf56b308a1c01c38091fd3e04c12b695de497d48bcc268d50cb0bed793b8e6937e8d533afd568521f1c9377a3804d38e785674d7ce868d289938e33dda6edc76d25b15fcb38852b7803cfe62f08d9fbd070957c4e6f134973964c9dc009985c8501e7d8f72e7ec285d5289fdd07f64d62acaa9737b039efa7a9d1d175577c6bcf9dddcf692877af38e75263bebe2453155be61f0723c274388a532abe29dd7023e327085f4c9dda41839b7b3357ab9d",
+ "message": "0100000000000000000000000000000000000000000000000000000000000000",
+ "context": "",
+ "signature": "2f46a132fd974317ee471039812ecae34d5fbf241fb4e131049f5dee3c5eb3085fcfcda617bec4d1afad7ffc39c77bebdec93133ef562144a3e38621d231a6661920feb58323d35030ddbedf2423375e781c1c028554dfcdd1df64afa4ba5425723e4b4bfbc7025864d1cdd0c50ca26281d9b01c8850fae3bed29a00935e922de053d98b2293847b544ac3edcf19804969eccd9d9df84f2a9a27e9756d051d3c029261bd3f1495783f0ebbcddfaa5cecc55c472394f0b8d40b1ec0f1ee827004407307ea4eff9d668f812b6f968e6fffda053b9a1501967b2e4c2fccc9e2132464a2609126a82561c8293bc63cb05b04997dfab2e6b22ace42959b5701cca700545edd251af7c8a93167c50bffcc2a4fef766d7c82cd44be8a2b887f4c3bf533e5003400a9fdf765b78c11d0514ca5d2e3a56e73843ab6d80c53356d8a050b9e6f39db9a3c98d31c641f289c02c6b8cbc3b31de54d7ae518e185cc93c0bb84942cc96fea37d838a5e1f4d4ed97a9fd02582bf994f3745ad8eb7a088784322bad045140d953657eeaacedd21fc387805dd0949835121e0dacef5fd32d2eba4a5925c84e1e7bd57dc4ad7708b94bd700d0aebe1a23975feccdf5269f97a88f8c3b7018cc4a2d750ca0c485fcecaf937791f272e7409fe563921fbeb182dc24c59a39f23f32cf5028519653f6bf880534a9f5627e12a34bd03cbb9e2cc5adb8871fc4b36ace15d8f513810e5114533a2239bb1023a78a827cc3edfbdd6717a26b263f19001e72c4e80c65d6df70a80e6e32b47d6c8c4e57f2ec83e929feda7f773bd4840d8018e40d55046fc98590c0fe2f964300c562e463a39284f13888bbc639c2262f74c6bfabef145b47bc61f63df6ec6b7e74d6d6a10c8265ceff1e97f730dbe0fb5210fba34b91f003af33e8364e31f3000b39f44e1a4f0541e5e2a8197e88ae80b7f818ee1fb5e70090b9d2c297096955e6f22e923bd70f6c9fc0b6efb4ead07658fae1c3a978cac7d6038c107c53a74c2257cf5d1b502cb960232d91dd7bec867a9e0f9a3353a3f98d3cd06eb739f099517db3841fec3b716375c2714d0662ba09b128316b0af220501c2606d5863811546fd9d9e78822baf7757999d2167c8674d43aaa093f72999e44fe5332dc3a17216b59a353b108b0ab0e9c11fe2100372d58ca8be2271c7b0bacbfaff8965043fd2d9863885e6a70c1e86124d911c12142f3fc7ceda18bedf36659cedd52e03fa4a6f06ca920494b7ffd87724dd173d28095d3893ade73aea2105161b888f6f069b00264108eb38c0d99962aba3867986b23c308d9189cd30489642433c157d843ba9968367c04d0a75f9143ec9be795475fc435f02ac4b54b131c9262ff9eedccfd10bf8b0ebd31f99be1424db97032464dddf1613d7f29a06abdbc34870e43bdeafefb895a56fc51068ef4935f53d77b045718896af2c9c348e7dac2e76c863ab2fef73f3fe63787e061f422f85d0d6cdc0fe3764fc14167324188315cfd8ba6d3a3fdcea7a1d6b491e42935e3d7374e63b829b0ee410a4fb547186357088d401a18cb99bd5562ea05a5c9b858a675f79967e26f5dcbfdcb298970457d4c12c06b46a4e51aff7ac70571e2806f1c6fb7d4c07b13e8016f61fc7e13ea648de148977e4ba129009326e14f1ffb307e4d387812b9acfb53b73b0207c1326f23fc90e4dbf297b58640fa24de73a5b4cd961e76cabe30880a00ff499667dabca3710b179abcd03869b6b5dbdfec9da56cfcefd69263c72640f4f8c238570fed26cc250bd5d8a1f147619ca396aed1394e3edbbec27562563a21df8e8c9d9b0a33e9f69a1e463192a30de65c02efb6de21a6402a0122f54cee95649a97c26af319a0ceade5e0d089dd18be5871b44879729ab2d0c5b3aa914836049e3d1b89fcdfc66d4feb418cdfdd99e52000dbdb01027ff83ebe016583d5f24090e175014c0336808cae677e198fe3fe310fc3de5a858a0b943de6a2c830a34e5f725512e63af81421716b947aa6cd5eb6997257c00475f7a9fbbf13a51a9c38467d468789e1ea5154f86cfb68d6d58e9c1332541a8bcfa4a73ca311a641776165c5b8f8b497c8ac582a5b87ac2e180d674c24a4d7e343b9a0ecf76da91ac954e0dc72deb799d05c6712dc65c0ab08f15c4dc8367e0fb2928cb134ad5297cd0a99adefbc860aa5402eab50a97804cd3df8daa85ab281910b9a1009cd3843ac0885eb1b8bca054ea92f6be3734396ef0db423197d16636794520c6f2e70cd1b1b2c1792b4d43525ca688bb89f4ff96bcef8da33b6eed7103ff005da2da8c8e841b87a6798cbb292c6f504b0fefa59a3a84099bb4f60016eeaac5949ca74a03480ea6255acc934df15d7e6dd15b67985a3ee2d6b38d9479914a4e9a708b3a868c6c121c36fe602cfd8a7d8f0d69cf8278e51072233a0e8304371b0374a3debcd42312e3cd2333be448987ddb7b244c51891cb5397c3af7c06067fc7ce8691247c65fabb30a89f8bfe5b5653e4320f651a366638f36f449b846e429026e92a229e1e80a6bd329a1c659b3e70d3be6b1eea2ea6c5985e74d21f127e07655a4674d446678a580f1ae7018633e8ff2f86e8b047b7702bcdcbe6279fd3fee8aa1be459bca64512cb129180b6168ca26a653bbacf99ecb4d1cbae06013a724988e2681a52d41afbf43e45f0652fc8412450c3bd5453d74168a2b599222d1a9ca52691a3304e21737f436bc266b871db8c255bf5a22f95a4d2d8b084827ec63b5f37c96f344391cb0657bea5f6d83d617d91d189a53cb8eca5ae557ab9f23ad562a6852784e44b248518ca3f518f734c464f3817b6f21aa46159f7538bc65f7c7f61368c8b415548082a616a27d471cf26e122c985aeb37135e3a85e3ea282a237e367aef2f9ebc601e97c5c7ccee91c80a416c2458efab6d1f8a07a43814368e922765c09c645519eda7005a599cf424e0e19aed7064cd36ed3a274b92f9a968c9df3145243ebef6fa061934ac79fc86e6efb9d93bb3677c46908f68c58a1055188f7bc0c5f8416667e4b1898c4868438aae777a465b4a382c4758f09e59e2c7caf7d49c0874f755b1f38e7000a55af11e2a669ac8fa389ff77608fa07e1221570c547884034251e6f5cb585e4c2d8fc044fc6245c1e0bcfc7680768ece411e92744fb7598ed8bdc11ceb5f1b7c1c5f24d7ca5c21ed4791528926967c74b7dfbfc4ec720456dce89b0fe34e1ac3f99cb12e0e4e1c1397067d930c7c471defc4a22ab62a30a2d7e22469510bdfac1688950a5a3183c9a5aa3010104070b1214273a4288cbe0e2f8fbff32548898a5abaeafb8bfdff0f3061e2f3e73919c9ea0a4adaeb4b6c2fa0009162f3c42445b5e6a7c7e859699a6bbc0daf4fc00000000000000000000000000111e2e43"
+ },
+ {
+ "source": "wycheproof",
+ "tc_id": 56,
+ "comment": "z_max below the limit",
+ "expected_valid": true,
+ "public_key": "db9ac67708f2ba0fac1f92bd802f9be89ecab966feef59872a1a9ac90b1111170a561290ae86b13968f2506023c014ba09fa449a26e4e9d35595e73986506cc8790e4d07a94d6c736f7ae78cc5e3e3cf025ce06a09252bef97fe92e94cbd107b1844d1a7c690d88bff9e9336f8f58e0bd5ee384de9c7ffbb149a6fcd87c77288601d8843e28e0c7a60149d02ebc57b183c39888d98b61cd8ad48135ddb8a1666743bb689f44c1a92d52017b6a8fa493eeb839dffb086a9a6c399b194a52f0e4164c96ff8a2a54337de24350a866b5fe4195257778e72511221778f1eae5fa93ed3532f696b9b0767aded85f62ea311027c7f5fc4182dcd2864b1c26bd6dcf72ebdedf70471327be0ea1c2ae53e46489c6dbefa512a78fdd7be0ad3ada16a7f7b1ece49817b44868a2cc234bfdba556c32cc92ec2c5e8a5d206f2e4ee372d41681e67d1b7e7b0061870c57f600fafca85f98aed8ce4ba76bba961f9ed56e563220d3ced853b6b28e7527da0e0912bc932a23c8bab811429bbb4d49b2770bcda44abb932b11c0a5866409fce39fed2b459c86c8f6e1ab0aefc5879503f4b21a49b4b2de6760c9b6aaf041144a656a26af39f4578e1d482ddc1360ef751d9784b860ec373d415360fe99f32e126a2ac1243430e8bed1bc90b19b3d219c2712edcf81c44b4331f6421088e662b695e1fd8fa5091f616ab60af70f159b63368f1ac60d77b279ed47ef7f24ec2044bb6c2bc76d933ecd568f7e663392afc1d335abac6c03670adf87747dde90052f5cd45f7d30f43a4dc3c500ceb658fce235c171240baca1b5a14733d774b9416c540f53eb83481afc98344b12a4309e6222b08d978430467497010314c6f6b8caf65361c216106395275a67d7500dbc120f7918c6f8db7aa63fa965b4a22c70dc88f727d768ce2bfc7597fd470184e1c59a6b2e1204cc8c3d052c594d5771e0ccc8cfb191f47038b1c0672f07caf4747562d3d76a9816fb1def1391cf0f05fcdbf2a0eb6c21ac24b26e74ee403133e80a79313ddb02c1fa386c6dd1d420195343e3a104aff6d60887f7304fa9e3bb59bb55f820dd85b1445c54e9a38dc1c7f3b88eb36a9f48d13455e51c934825ff3cd8bedb2b5422344120399eef83a360b83440ebdd8ea6e01c95159e3735bb4408500caa785ca4049891c7331c4ea31ad9060ece768fd339e6904f88e27bad3b28845687be2cc9314f300fda56fe3ff2508e54c59123b068f86fe00213d5af8da1b1735423ed688f097c306dbc121b81f532fcaf872d9f80596642295d6e4bead478644081618ab903b39e9b5e7cc0b5f2742d8337b18d4ad4788db7443e946cafc1762a5da84070e8c2fd86d6c633f0b44ee234ba11b9e1440c94a08d0437015279690405353059020fd2f58f15dab18754177244adfb81ceab79c7840bf3884a3d364afc8c453a425fd8c5378eaa7445f8c6256bfbd03a66c53e8cf27e2c52f14ef3294afe79cda408f5dff933ca0211a78a4e3be3d9a932558ed71ed19bbb57f87937fa3d4a78128491ff096a261045bdd186325c42caa8c7564195a4d2499a1c17d21a52d1aacd221d9c8a1866963a20390f2fd43dcf56b308a1c01c38091fd3e04c12b695de497d48bcc268d50cb0bed793b8e6937e8d533afd568521f1c9377a3804d38e785674d7ce868d289938e33dda6edc76d25b15fcb38852b7803cfe62f08d9fbd070957c4e6f134973964c9dc009985c8501e7d8f72e7ec285d5289fdd07f64d62acaa9737b039efa7a9d1d175577c6bcf9dddcf692877af38e75263bebe2453155be61f0723c274388a532abe29dd7023e327085f4c9dda41839b7b3357ab9d",
+ "message": "4800000000000000000000000000000000000000000000000000000000000000",
+ "context": "",
+ "signature": "dfe343f52cd8b02b7e88bdb005c9a7388c7b79f2eed8e5bfeba82fd0af881dbf2903ec43d62e2fbe1bcf93932dc1f23dcd5c37fcd983e04c39798d94fceaf467145c1725980a53a8c0a91f50850789642b8eaf7ad51d07f61eece822a8746eab811c02d0ab6b6ac7a253a3a7e9cbf0db24bea21aa4af4a81bd9217982be2de73b05e2cad8a333e07d1db4b9bea89188cf4e352ee6b7358d4f36a0172e475707231c95fa9efe7c0be8a3c3f6d69eb02f758e58d2d45127237d0a6a297c385cd3fd1275e12159a9fe308736b43a6b07f73150be6188eca2737fe13075f06a07d89246842cb20914802758e23c02d6574f90367df7d03eeba9854c9c7a3ab50a590bf9560558013581826b9d2f580864157004ca797141f2ee2d5c53dfcb54486aca1e45c00bac15427c808f07e26dc58d0179e335fc03c3481fc150ec60e51b6dc1aedbbf063a36d6281a056b3e8ad5c5e05e7231712e5f8f5b3a143010859b4e0f22a1017ed9650e10d6c6ed48bc46a3db05cc14a492c7cb20b3645c6cac987ceaf6a1b76de185ed957778536ad3c4e01976f2e94fc72d2d4600081c3ecf8df85bce36ed432a8bf56ac376363576defb499dff634217b04cd6d88577da65acb831680bb6a71c7f7e6aaca1aa6bae12d64fe1c6ee6c612d2bcea338c8cf853135242711520efb8c2170cdfe5f058649b6c91231fd42144bbf1a726ef9ca7934fc301c48274e994cd011f1c42d24d90441ca07df7696b9dca3e0594cc1b120616d9739af9b6b56792caeff19e3a24b7e8a85184b4d37bbbf1379af62963ca7a35cd4bd707bb590ae078cc7e37c77b4f60a10bf61a49843a2d7eafb611371bd0a689fc19a195ebbedb608692e16cc7bf958b2c701a111d65f32176181dd1086df6e96678027388e5861402f76259b7f0429e2b910b615c4ba0d9be48ea809acb4ec632f22802078aa09ec62cb1a41caba18d63edc26f8e2397f2baced378b55fa4947eab200b5ed6e084728f9c8b142e4c5e36d9612b1e8e47da60bf3147c8be7b09fb231d6333aee7ce8aad378a7b093d50103b5b76488e5f19859acd5f2709bc5a38e621ac11139209c97713f490f25d0d162e2607e5b6644293b546e7b2662930dd25fa3217c8047e7685e1f89aa76badfb11b01b654caca3bd3c3446c0aa142e7b3dbc469e4dfa1b175ecd3c63fc205bf03bacd97e3b20d89c0ae1e1f653ef0a3660281f9a0834fc1ce1b948d1186a0a2045439a196d82e8b7a9fbcb8c39913e81b177a9fefb9e1187686c3f5608f8636760d87490b0e7c17ddb87d45ba2edc2fd98808bdbd88de4483b96668ce7032d2ca085dab535cd2ec5998d7a2f0aaf2aa10a0f28773562f7a5d3e70a51ff43240492ec75825de0393d49e6bd03ad2f3b8ca501695f78d898bbf47b3a686d4d82d842ee727f05bed87c2cd8c4fd83304e19f2282d003aa0eb00c2c164594a6d90263754904ec2eef3e04bfc91263afd651bcfc24c73fca0d15adbb4e539a5e6c29db82e1f04546c6b93b83f458d1dd46c3f5e06b35c5e68645652f9512320d295ab864c96b8b9adc6dac6f5571912109c7dd6a8cde991124a6b223456913a3bd2ec4fd53f6edd9fa9dad4ced1013cdee1b9549a02d92068c715f4dfee8b5f4e409a9c8f7ef2643c64d466e176e6b6c61fe3e57f901d410d5d29d25f73a92ee57d2420ca2a628db8bcf940ca0a77c03be87e50dad4cbdb76f33bcc3957fb1e105f0a1ec6a6a823bda552b70d1fa9440d6aa428e170ffc9c16cf621058c6fc2aed2f40d67daaea9124f1ca26862089a18fbdf174255ae3ed0fad143a4fdeb80450b93443317b9cf592cf5a58da86de34c17845ec86a51037acbb5858b5ad6aba69efa83cac149ac9ec9a344fd152abfe1a04de7ebcf6fb0ba7530db08499765b7d5471f101d75a3ffc276009accc5ccc18583c921515e018cfc50c3adabbbf50347f864b1110a0032be50bdd75edd36c9339a9a43575e6147b6ac2740364e6866f0939399ae28e5faa7eba4e7bb852070b5611200f486a23ad245cec296d90cea001d87adfe119e9ca7aaed3ed99a9efa007e5068345adb680c2653e3b90edef518bae3bbb22e67867aa6117aaf833497d7eb3d0f93056bef6a6cd1118b5994a7b7b8f5199ff8461f00173ce254efe9222ef3cc15d4fe5f6b845bb0841dfeb8625792fd310a5d3fd136f28e303009e3132d47eb5a5367a712e34ba0dde4418fa9b606ab07b972fd0ef074e3f0f5a623c5a563135b3df0b6c3cd2ff33401dfcb914da724126340a171332730755bb2831975a721f1a9da0c89d88ea10ff7ccffb98259273f64c39f8308c2ddd876f320436e4ed572601f2d3c4a79477949bedce0660e7dd66705ebf1177e3744a824876a0a0222af69da59ea510910aeabdc5b3674337771114c47d9641aed3a4927ae517f16d7195a962c9c97c31d6519d8456a089eb96e3ad88b3c32fb927285c2fd37e042e83fe3b853e65a00540002f2d65a25e6b23a623ddb009e71ed99e3d76b5ab22bf61005378a109f738ab8f93216b4267941c54db49b8c64252a966dce1753efe2a50c91e57723584a08e7404ae6836c59da97fdc8d3aabcbba08145a16641c60891b360d1105161701d2042708767b83b1f5961e1eb123e2095adf8620c3e92db92877b06d3f86b881cfd170aae23e6dc4f7e0b4e367a61f5a764c69cfeaf8f92bac2b5ae0972c3cf0df0c00d1a0bc0bd441ff98f7a21b2e24e7c9e65c49a4aede9c35638ad02ac08097a7854df30bf0bc79eeb98348fa467f299f84818374930171b56aaf9f5d017bec3dbc6feff268174a4d6ca77eb5d3662b7dd8dc0aa58998ee371e0cf6fba03b131a2161a457bec7253dca23cdddea6a4384150481a9eb9fc79fbc6845dac0dbfbb376f2f5eba1d77a9635a902495d14f6550cbf26f4b42804bcb53d14b8c94e13e9cf9567cecbce3898fdbcd8fb71147005cbebd42ed15407f58925d4291021beb9e4d15105f3806d51c2bb2c4624824a2b5218bcd7ce5abe9989d8e4b0c9ee3aa8309bb73e676ee3b3c703be0e699417bff5363b4c0b505d8dc622f886afca74775e72e6eccef9e6ad22f166c3b48e57fe95a6320c10ae5ce1dd9cc948215672a3d4cde80704ec6c009e2aed6c4f0c1c7ac8e534a20d700f1201ba2ea63304e073bccf033f47da0175f870fd48a88b47760c22e5603d7f3fa0f928d5b968116cb86fe156913561145b7af61e6b686de2d124331e52cf64393951a687f830464b50e71295a97ab059c545a310a9659d7f22c8f114efd09141c1e20263a50939ba0a8b3cacbfa0f1d212731494e5b73757ea5b6b7bfe0f8fc073f4856656e849dabadd4eaf4f6031114262f3474758491b6bcbfd1d6d8eceff10000000000000000000000000010223043"
+ }
+ ]
+}