diff --git a/circuits/benchmarks/README.md b/circuits/benchmarks/README.md index ddd61292d..63c2f3562 100644 --- a/circuits/benchmarks/README.md +++ b/circuits/benchmarks/README.md @@ -19,6 +19,32 @@ From this directory: Options and secure-only **config** circuit behavior are documented in the script and `config.json`. +### What gets stored (secure / insecure) + +A full `./run_benchmarks.sh --mode ` run writes: + +- `results_/raw/*.json` — Nargo timing + artifact sizes (source for the **Circuit Benchmarks** + table) +- `results_/crisp_verify_gas.json` — verify gas, calldata gas, artifact sizes, and + **`integration_summary`** from `test_trbfv_actor` when gas extraction succeeds +- `results_/integration_summary.json` — snapshot of `.integration_summary` (phase timings, + folded proofs, **multithread / operation_timings** after a fresh integration export) +- `results_/report.md` — rendered summary of all of the above + +### Regenerate `report.md` only (no integration re-run) + +From this directory, after you already have `raw/` + `crisp_verify_gas.json`: + +```bash +./regenerate_report.sh +./regenerate_report.sh --mode insecure +``` + +`crisp_verify_gas.json` embeds the integration timings; if you also keep `integration_summary.json` +in the same folder, the script passes it explicitly (useful when gas JSON is missing a field but the +snapshot is complete). `regenerate_report.sh` itself does not re-run `test_trbfv_actor`; it renders +from `results_/raw`, `crisp_verify_gas.json`, and (optionally) `integration_summary.json`. + ## Refresh after parameter changes If you change circuit/config parameter sets, rerun the full benchmark + gas extraction flow. @@ -43,6 +69,30 @@ pnpm -C examples/CRISP/packages/crisp-sdk build --gas-json "./circuits/benchmarks/results_insecure/crisp_verify_gas.json" ``` +If Π_DKG / Π_dec **verify gas** is `N/A` because `crisp_verify_gas.json` came from a failed extract, +but your integration summary still has `folded_artifacts`, replay only the Hardhat `estimateGas` +step and merge **dkg** / **dec** into the gas file (no Rust re-run): + +```bash +# For secure folded proofs, align Solidity verifiers first (--build may take a while). +./circuits/benchmarks/scripts/replay_folded_verify_gas.sh \ + --summary "/tmp/summary_secure.json" \ + --gas-json "./circuits/benchmarks/results_secure/crisp_verify_gas.json" \ + --build secure-8192 +``` + +If `crisp_verify_gas.json` has `integration_summary: null` but you still have the JSON written by +`BENCHMARK_SUMMARY_OUTPUT` from a successful `test_trbfv_actor` run (e.g. +`/tmp/summary_secure.json`), pass it so phase timings and folded sizes match that run: + +```bash +./circuits/benchmarks/scripts/generate_report.sh \ + --input-dir "./circuits/benchmarks/results_secure/raw" \ + --output "./circuits/benchmarks/results_secure/report.md" \ + --gas-json "./circuits/benchmarks/results_secure/crisp_verify_gas.json" \ + --integration-summary "/tmp/summary_secure.json" +``` + For secure mode, use `--mode secure` and replace `results_insecure` with `results_secure`. ## Reported protocol tables @@ -53,6 +103,10 @@ For secure mode, use `--mode secure` and replace `results_insecure` with `result `C4b`, `C5`, `user-data-encryption`, `C6`, `C7`. - `Artifacts` for `Π_DKG`, `Π_user`, `Π_dec` with proof/public-input sizes and gas columns. - `Role / Phase / Activity` for P1..P4 operational cost summaries. +- When `integration_summary` is present, the report also includes: + - an `Integration test` section (end-to-end phase wall-clock timings) + - a `Thread pool` section (Rayon threads / cores) + - `CPU-bound operation timings` (tracked in-process averages/totals) ## Derivation rules diff --git a/circuits/benchmarks/config.json b/circuits/benchmarks/config.json index 7b1371cac..6bedcf83f 100644 --- a/circuits/benchmarks/config.json +++ b/circuits/benchmarks/config.json @@ -6,7 +6,6 @@ "dkg/e_sm_share_computation", "dkg/share_encryption", "dkg/share_decryption", - "threshold/user_data_encryption", "threshold/user_data_encryption_ct0", "threshold/user_data_encryption_ct1", "threshold/pk_generation", diff --git a/circuits/benchmarks/regenerate_report.sh b/circuits/benchmarks/regenerate_report.sh new file mode 100755 index 000000000..af620a42f --- /dev/null +++ b/circuits/benchmarks/regenerate_report.sh @@ -0,0 +1,3 @@ +#!/bin/bash +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +exec "${SCRIPT_DIR}/scripts/regenerate_report.sh" "$@" diff --git a/circuits/benchmarks/results_insecure/crisp_verify_gas.json b/circuits/benchmarks/results_insecure/crisp_verify_gas.json index 6169159ee..d22685ed9 100644 --- a/circuits/benchmarks/results_insecure/crisp_verify_gas.json +++ b/circuits/benchmarks/results_insecure/crisp_verify_gas.json @@ -1,10 +1,79 @@ { "verify_gas": { - "dkg": 3037849, - "user": 2972953, - "dec": 3549211 + "dkg": 3037922, + "user": 2973073, + "dec": 3549077 + }, + "source": "folded_proof_export_plus_crisp_verify_test", + "artifact_sizes_bytes": { + "dkg": { + "proof": 10944, + "public_inputs": 416 + }, + "dec": { + "proof": 10944, + "public_inputs": 3488 + } + }, + "calldata_gas": { + "dkg": { + "proof": 170112, + "public_inputs": 5504, + "total": 175616 + }, + "dec": { + "proof": 170100, + "public_inputs": 16664, + "total": 186764 + } + }, + "integration_summary": { + "integration_test": "test_trbfv_actor", + "multithread": { "rayon_threads": 13, "max_simultaneous_rayon_tasks": 1, "cores_available": 14 }, + "operation_timings": [ + { "name": "CalculateDecryptionKey", "avg_seconds": 0.109839375, "runs": 3, "total_seconds": 0.329518125 }, + { "name": "CalculateDecryptionShare", "avg_seconds": 0.613667722, "runs": 3, "total_seconds": 1.841003167 }, + { "name": "CalculateThresholdDecryption", "avg_seconds": 0.567017042, "runs": 1, "total_seconds": 0.567017042 }, + { "name": "GenEsiSss", "avg_seconds": 0.12360793, "runs": 3, "total_seconds": 0.370823791 }, + { "name": "GenPkShareAndSkSss", "avg_seconds": 0.224165903, "runs": 3, "total_seconds": 0.672497709 }, + { "name": "ZkDecryptedSharesAggregation", "avg_seconds": 8.543418416, "runs": 1, "total_seconds": 8.543418416 }, + { "name": "ZkDecryptionAggregation", "avg_seconds": 49.652658458, "runs": 1, "total_seconds": 49.652658458 }, + { "name": "ZkDkgAggregation", "avg_seconds": 20.662634083, "runs": 1, "total_seconds": 20.662634083 }, + { "name": "ZkDkgShareDecryption", "avg_seconds": 1.446775729, "runs": 6, "total_seconds": 8.680654376 }, + { "name": "ZkNodeDkgFold", "avg_seconds": 78.077101958, "runs": 3, "total_seconds": 234.231305875 }, + { "name": "ZkPkAggregation", "avg_seconds": 2.185247625, "runs": 1, "total_seconds": 2.185247625 }, + { "name": "ZkPkBfv", "avg_seconds": 0.330690194, "runs": 3, "total_seconds": 0.992070583 }, + { "name": "ZkPkGeneration", "avg_seconds": 1.336457333, "runs": 3, "total_seconds": 4.009372 }, + { "name": "ZkShareComputation", "avg_seconds": 2.652245451, "runs": 6, "total_seconds": 15.91347271 }, + { "name": "ZkShareEncryption", "avg_seconds": 2.472213376, "runs": 36, "total_seconds": 88.999681541 }, + { "name": "ZkThresholdShareDecryption", "avg_seconds": 6.197666847, "runs": 3, "total_seconds": 18.593000542 }, + { "name": "ZkVerifyShareDecryptionProofs", "avg_seconds": 0.098564625, "runs": 3, "total_seconds": 0.295693875 }, + { "name": "ZkVerifyShareProofs", "avg_seconds": 0.216449474, "runs": 5, "total_seconds": 1.082247373 } + ], + "operation_timings_total_seconds": 457.622317291, + "timings_seconds": [ + { "label": "Starting trbfv actor test", "seconds": 0e-9 }, + { "label": "Setup completed", "seconds": 2.979362292 }, + { "label": "Committee Setup Completed", "seconds": 20.254983625 }, + { "label": "Committee Finalization Complete", "seconds": 0.006196209 }, + { "label": "ThresholdShares -> PublicKeyAggregated", "seconds": 379.382091875 }, + { "label": "E3Request -> PublicKeyAggregated", "seconds": 381.9183135 }, + { "label": "Application CT Gen", "seconds": 0.3119425 }, + { "label": "Running FHE Application", "seconds": 0.003318833 }, + { "label": "Ciphertext published -> PlaintextAggregated", "seconds": 80.313326166 }, + { "label": "Entire Test", "seconds": 485.793576792 } + ], + "folded_artifacts": { + "dkg_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000e1f2dc40db945d42200000000000000000000000000000000000000000000000bc38cde1aa22cb5fe000000000000000000000000000000000000000000000001d3d59501c65c5e320000000000000000000000000000000000000000000000000001fdb65cf5613b00000000000000000000000000000000000000000000000fea025eb701a09f610000000000000000000000000000000000000000000000099a31d5419d58c50a0000000000000000000000000000000000000000000000073ab1d4ec48035430000000000000000000000000000000000000000000000000000238cec0a15743000000000000000000000000000000000000000000000001e876fc999cef26f50000000000000000000000000000000000000000000000016ff1d86d471a44cc00000000000000000000000000000000000000000000000be45a89750c5a5cb80000000000000000000000000000000000000000000000000002e6bec9594479000000000000000000000000000000000000000000000003e285c4315d7c37980000000000000000000000000000000000000000000000045c3be92a35649f9f000000000000000000000000000000000000000000000000774ecf2be14f05ab0000000000000000000000000000000000000000000000000002b53e01a9484d028db3b0372cf70506ceb36d180fe176feaef4cacd38465840282d05d98c83a126caceff591ab92e45fa2a8e93cdc4c9da6620778e8e22c5b29c868b75d9b6e310d3c31ecd03d3676db23158116188c3e53d9c5361beef5528604f875d47f6430da4b0162741a4478a6993c322ca93eeae2162c546adf69e792b22ee7d40fe9a29721ad2ee16d01f9b344c9dbcaae3c3ea3c5a09dde1dd269275f9cb213b601b1bccaf864b9cf3cba884ab06b1235ea1ad09d25f9f5ae4a31d453c8a081af6f71625c44567b2fd9faa5491cbe7332c645a24f9c9c948f6fc3ff79f4c8cbeacbd0695e4561a8b7d0b92761edfe763e39983b9749e2cee9517b2f80591981f8361072b10967127b862ab5b83da376af0c1ce237a9a3a17076f970f9b5fbaefabb21e6b66500a97693693d1b5269a3f172d2b565e8fd454e200884091bc9c0822271de3d2014a99fb2925abedc2d016d026b90f03aecc9beb5324f29979ea4a64d4058ed291ce1c39e1d4d9435d8831edea733ddbb559c3a5a97baa1fa02fec3e5c252513658656267eb506430a22753510795a9bec9154b78c5732be8217ec0dc82312dd0f50f7ae7173242a014281649b0ae63ec26096d0ae531885f0759ceb8503751681ebb1062e969d66f1e5e7cafc78baffb7f8b1a455118bb9e1446520fc0525be99999487ddb1253c1c336fccd8450b731aa3ae847112654a56da7f02a2272b733c9b7d31a2e63a37387fb26d8af57a40845e709ba3c4e1c8a898a237a41d0bdec5d3ee7ecc282adbc192dfbd6a55d36de4930f40667fdfdf1c136643b9014bc9340f9748760531e6eaa99075b60bfa8efbcec485bc643cbd1b78463183069bd6487a0fc8172da864dd6a0d3e47fe3be391914d6c81e329bd2a764f47c52f4997c3f2a8430ca679c99a6f0e1ffea2fbd7a0492d0ab6cd393449dae9dbfa2246c5afcfef78a77f0bcc680c1de1a8a29f3fda46eaf9a7ace14165cbc2a076126629fce549bc56da5b7c24d12bb9e3e8dbfb356e24dba1f622793345b0dfb50e525c6f6daa65286edbf55e9f5d56a92e82924936d882a31c9dc0310e5a8ddb08ac158364c37634bf8ebee1cee1e7ba5394f1e10b2b83d0b1b5ca5c34cab202274a01af3f501c8ea02f6986db0d8446b1827d4fcd2022faa954e78e9aec3bb8186a26ad086a6549d1fec85312e028556f7213e4a725a976b266bad87a7c6b4f0f1cf3ce1ccabb1f11f3ff9924857227d0bf3efc6c5f8316b8a12cdd3e7da4481609dd4d212555a700a26914de6cbd75f7dcc6632915094c61ec6ec24eb813170c5a395a67b0d3f35934478aa0989100db0e17e294fd55702df7ad7f3c73931e141a4c58e29829294f9c268d7510c42675036df15feb6b50c7b831d297790aae0f0c3b75bd3e146d8e0ac2a60fe46169f324131fb647cf4d2b750fc4da9e62722de86b0517bfea16566d87b43dcfedd9f650f5d8333b1774d9d6f8b77c015f122bc9d45ac7c05143beffd7ddaa1ac8e69d038ea603ccc156b780b67286b4e96c11c455e5c1df524c5ae657e746ef3e60c8f6b0da74eb476af1e0764199d7ba633054f2cf1eabf585712ddc151023578d2ef9940601597a7681cb0c2b89d1c4b43053df73189ebf5aba935cb94bab2103012c5bc86858cd001d252d72cb08bbba1764ad88e8370c2f76d3c979a20c932ce5edcec2b3f3c371a97c2dac039c6de9164805143e1705d96e0a10f1a419d7a4892e6e870be740ac8aae4cee4e27ce15162d0f514bd517e1cf13d3436600d54ebbbb0fb1727bb2839790d7578e01c924272bb26dab779a11b0b5d805ca706743dcb200bd6dbd1ca2f0a6453ee396afca109816c66dd6e17030a57ba31b9b46b476312eaca02f732cbfa5325295b450691fd3249e466f3311f99a60d01590c1f85ade3d2f0de3ff9d98b88a216377e5a32b6fe740893e4e5fe67a1c93ef089f631e2bed3748ac5d7b9849ec362b7a8e4f11418c50ec3d14891c877c2350771170f90463e9764438b9e73c30a498cc23d403c209f867cb54041c87dddf14e7a0170db0084921caec1c69c442473b83f12214f4fcc66f1aa3d185c8fe2925f3115dcd1bae3e97a757b08882ca10d6ca5b6b149c499952b188fe388719511ce1f127fc7d706685fb33ee80e774d517bdedd01344339ee00a74b2dfc3511f2d93090ac1314cbeb41c89f2cd14617b5965696e0d18b8d4e3c13a0a661313a7af2cb8c4ad7a4c6a0322837187e5f6de5dbaaa74207144c4471a212ff3cdf337d1f749e3cc24e4241b279e73903989dc24a3057c00cc57fcb3f1709bb431c38a4a97873e91b223c6709f18ca88affcbe7f7428c00b5ef61bb8e71042c3fffc919dccd7c09e9ca069ed1d7bb77c4c1acaa54c51f4169f20c2dff03bdcc71572044b5b6a185f0eaea935dbe0203c676bb6c04b83591ca94a869929dfd662fe0c4357881fff436014d3aee362554a5e1d9be1cf54450bdcb6e51c2e1ec340a774ae942f45ae6827afa23bd8b1b8e8a9b732240c66bb1dcc84ab5611af066b0c61832e7db92acef04757679cd81f94ca1d84020b8c0a2dbdb1872ddc0fc91bbd3978810b6820aa2a336a1d97d74d39e82ca9602fa4ea23816c4d133fb820681076e7cdd6d3bc7d0e5e15a6185a1f3dc60326d8cd8a3314a0a1598892960a9b9fea1cba9fd1d2c0e56fcbef30c274232d0d23cbb9a97a0db15d1941f5a64b0dfed341453ffbc79b7fff1c105f3f595418fcd4de049ae1216484d67dd0d53644f49e42be07ba8ce80fc7a3f0b3e8d72f6deaf93d43cae5201f33e07ce99dfc3b88f89cfc55e50be50ecec5fc7d8c24d189057556012d8113a536bb5af66af2c891bb5fe1a3e7830d73ea7f2677f7010ad0c2df1f11cd1c2ed2eabfd9fb7d58cc1c2df2e34b1668ce803f5f9822b6d309bcda7eefe05b482d6019bd64419ac04ad495f3c5219db56982f0ab2f6d8a5327df9430c549f33d1cba8fc85bd28b2b02b23bbedb51664c20d36cfbcb21980541007bd6545d997d1670dd8db62cb6b238af1c3374d98c4e716693d48e51de2d6d6c92dee172c3851f1c7c1bbe04129d02babd13d4420449dc4c70d788e85d29e15a59a780792fa20d1c823aac167c73513400294f418d615ee959a346fba56b59ef109d519688ec13baf06d5c95775d545cee9e830b863df885663184c817027573b31c611c180e1b8d6478ebe1cb9153a24568d713e17148f00e241c5ae94278bc3808c18f96f90699f6e4d7d08014e0bc172ef673c497f8f7c4b899287255b79a0ad7e995051c2aaa0d6c31dc0be7550c9f795ccc0fdf44f2f7c6fdfe3be7b5f3f0d477768b371d1f8f97c97ed109c28c69d38e79ab3203b42cea09d33ced7755ba8d6ef6f877206cfb2b1c967ae1789012cc8ed894d6fae2e7cc2f49c797bc69f40c26f42d7c0f1fd1b8e02dea8d9113c1d96b08bbad5c3b653564840206871aa2bdfccffd6824826e74f385e5df25f73c4adc48ffe8e8d2adbfae9bdb911097a8ba4bf3ed9426c46e6750eb393149291727a7a207844299aecdd9af420413435e676f83bc50120c6542706abf0783d001ac68ebb33b72657035e4abc28f1e2cbf8593cc87c60ccf030125853b79419c3f6aabbf72b7a2014a35dcdcd07446bd08731b7a7110160076de37150cc9af5785ca9007a79cf551f3897eae9a4ced3307f204a975650beaf97b69d70a3c471cf295fe0bdf4da169ecd1c87c5e1df7aa38d0a8a89d2b2c4ff73d6028e7b321787cb5c6845264044ececaa3d6316f08169beba505f03b0f371638b194d13d7bd52fc56bad6242374cc161d5a74bad7148a41dbd49e44104c2336b17615c92e8a9f47f813dcd15e14ac26b160917e4e8b6150a9e452ce9051562ea0695ccfacac02fec03f930736506585b5876c34cc0f3e8a569a4f9a82ae3890e9ce939ae014d8699bb8c52b878556f61d6b28d6c85919a2e323b8ae20887e49e89bec0daf0656c9120e9a96ab1fb8a90cf22093b0208bc132aa8210c04b3b3749b3e18e1043247f34f5345143687085de6be3855fee3f57d3ff513ce23c71d2a3899b298cafb94598c97842c8b1faadf7ed61adfbbaa4577a946392a22c0ff3cb996a5b44eb1fd0b19b45bfce324a3abef53318b7b21f9e8ae564abb3019d2c161132450cd3227d31c78c36a3dbc01d9b97e9dac60c03f21066e9e8a1d4049add692584efb394b7ed23d3338bcf6ce90e4d614337744086930f897380b0296ac58833f4626651e8a5033b4f41b857d25e07f22153e90f6d03044584506abd763a0f54e053cec4b282ccd77b0e4912e4ba6aa6d0b8ba6458cd56024f7074bdd5e6b18532311f08c3dd81d482ee3d5bd269db8b9c8cb4134fc5ef7ac9519276bf0bf3ad7cefb8d1b1e206af5fee249f299bb70989cb50be8c149f18adc0df9bd8457efc268115d4eb01c46f7c7728a94b6406fbf850057222940eaf2fa22fd608966568e80cabf0c7c3274778e47a14c913b529f2ce5e41296942796cd221a94b824646c499d1916ad60e6b2c8cb06e0c6f02c593cb79344ad4c0f183f2bd17d5f4a59548c5d1e6497b2bf9c195248944d1a062159a4804c0828ffe24702e0300a14648c08fc78acb4610d7ea21ca0a8a877960ce2875238ac8f122da404d301c6194fe1bf1cfbb76bd5d84d049a6b6b8380d32cbd3fd6a93b3ab6e31e025ea99e6d366f7eab33e3bd3365bd07df2fdc7accd091ceaa43ca8005942bb92969b0501030587954a6f94719ff4c53cb87cd342424cacfbcd2c284cc652ec315984ac8684998283bd511340f76097e078a74cb26adacb197b2c7df6b8f71a50ff0366b16dcd1a995d3bd680d3dfff9eeaf2901f445b7d39c72cc502c4a17172eae7b16fbc7db17747f5a169cc67969261116b20cec1a21f9bbb5a381d0bc2619803fade69ba794caf697a24ba3a084536d378ae87ec8b7dd87a503028ef6c326a543ff92dad061b8acf90585b29007c3af670dff693d372ee4ee164afa72ab277c2b7c772a0b0c1fc3e0416846a8e3b43a6251d65f38b121a2da40bb773e5825b094e1080bd2732a64f67f01927abc8fb023c796f9aef4bbe76e1a2b1bf7c029882febac380e575de30c0321f451015d2e0109d8a8f9d69ee2b273e0bfc5581211b98ac45dc68f2537f206e9cffcd9bccc8d80e521c20f5ca40992237cd52407e2ce52223e2c089f41fa88b205664e811c1a65502c157a54b98e6642d472220f0e3dd61fb5323acbe5dcb718349daabeb0374c4ab79a93bd62f129d9a7f312140f3db2574888a92b2a7e249b6443e85b8e9529790dc9f95608b357b9aead2b1d855f3bd0f80a1f2bd248cbb85865b79bc61e66179ccb345b580ef58f9a3a760b67a3485360224b3d751c322cb56abf23754313e72110d45bf3639825f9d7bb2b1923960719645aebd84f78359c06ae775dbe1a25554aa421da21690af3cf1a2951448749cbb6d29dab6b92bf2d210ab5f5c32d822ca18f306eb069a8499649026130d680090d629337716429962f4b6eac00d442d246be012fd7e37b9d5f0626466b7ecbb1f0d85eb3864e455f6bfa4997837223103547f357399a630531f313f3240cc6d0e6b8957e8b5d69e3e1afdcb00acdf9bfa44c0d95aa8486cf124b06b845b55663e7b746b967b268fe9aaa9013a40224cddbd437ff0b28e87f18421d3b9cd997000b5c1b3c8b3c07ad4cc51fc491c740f87f0612ec72921266200a2ce15ab03a1689ada9e38bd4af596ac0cfeb07e01f2521943c8a50010801d0fc2dbe6cdbc8f4de88a4d641e5e6a4054bdf369c6f4aac9c9c8634dd42045ac6c9026245f2b6211ebff566030cdbacc8a9151b4365c3f3d91771fc1cab73bdee61033aa539963bd1eca0d7b486ad1aae7dcc1a392e1a6d7db4ea0009402c8f5d7a1964bb1a83eec61f1c7244b3f3d2cd5afbaf399353f50c8e40e0d17a318a8bea1f0c4e79a6eeb53c92891488bc03e497b65831ae91a19005a8b8f8227500091215ed52e70cc1aa437cd82d3fecd2ad70bc347f4a568aa0fe554042bc9d47ebd4118a9be9290598a834ea2ed2daafa454db5dbaf116b5170592ee3bd1b46266770d4ecd15581ed4fceb62ad1b6f31f449db9b5e84e6a6b4026f6624f41345ae480f2e10b0e0e8ed6733445ac0c95c15b47696e18bb98b565d8504c5f5c9bb622f09ea37cdc758effadffb92b67e60b0afcfd43b62d973e14118e33b155ad669ef0bc9051e5600c0d2a84b23adc3ba853b0782295a3fa26c8050330bbc3a572e2202cdea01102f516564eeb5623343160f618982961c575f5311d6dd944159f70b30414ce37af4bb47af31ecd55f5f9f438529fb85aabf086f81773cc11a297eda078cdf01f8e465b7db2f43ca511598138ea42dd29529cb2540e393e108c9c7d22342834557be4349f59ec0eb22e9c41b524dee8f80668d2d99bad886f7ef4a841ae383810c231158a1186cb820e96e9b3e238886c347a0ca9078034370342b112b3121064cec0dd115f748f7bdd7be79c8ac93d19ed14061927bb6fd14ecb2851343e9fad4d8deee07b1b45fbfeab20ec37950b5a684398a8870c61e3adea38d2e5eb4147e5dee9cb6c4a7a89991f7bcd0386b398dca56a3bf8197c7a4a8d22b1441d68fe280ad37e614d45bf5674dc2cde26180d1d064b854724c92532c065a07126b8ff084978b0a878ce40552c2797bcda00b728c74bb3fd8d8637266806216dba4fc94cd3829d05b25cd3f53897b3df62037a6ad6197c3e574bced9421ea1e499047d8270be2a4d17b31a054180724adf1a32b247b5fe8651d75e35edca30e57c6004eb2b5041c38acd34cd374b8e463ba48b97410f0241ca9253ee6ea8d29e0eedc285a0f02b8c7cb1dd62690bdfdd2669d3ea66a205fb5af1209cc542e2d0fd455feacc7d469102bb6204d1007c22fbd2dfdcfc2da5c2eff159fc79c342ca7694709ea4b1a72e320068a09319740dd1c1fe101eb4bfc744405c14cd9ea040cbd0b032af7f4940ea54c7b4e4ffa217928d281e951cd4c918be9778f685e0f8981ec58444cf6046cc7282cba2f6e1ccf0a35204d15e98cd5a5e36e5a20a826cc9ddc82e1971b55a5afbd0b186ecc156eb9c7b53654543dd081f8ce04c8012aeedaeee9220a1532041c28c63dfdf118b3762b4e506ff046335f5af87831be25eb3e9cff93597b7ba31a0035a69882635076ae9e72d56e67fdf6604223cff50a0df54aa08c3e1702fecc7910f27d8dabe86225e9601a0f4977f7b287270f090e41b023ed2383a9cb1e11b9b77da6f0cbe6f6c47a0d19ef311aea2d1843f7d22e374eab5e32cad1499f66162b1f5d386be05cada415a74a9b259a45fad940490843044b1e53eff11e4c7b59a0d817aec0f2068e8e4570d2731c4a2e0b7e1fe50f3c4965d7d9a8e9325d3e57247d56dbb9de92c3042d9996b68c5520f1d6927320464ee7350472a325e188ee96e48ab306add1b0060d4aa16093461160a01bdb265c5bea1bbf59028f3ea0f87b7bb03732ddb3cd405d305153decac49a390bfd0bcc40de0765136f65cc1c007dedf308a8f30fd3e1e01155184026904c9f4ecf03193af1d7f197219b2dcd0a31eb02bc3a498c913157be05eb238d6241422e692135300ed974835179d8c114af12be32df6795dff0e160bde9a5855d3887c3310c5d2ca5a5b80ecc1db01e70685b2e33614ad38c65597487130860c3e1f918cc1fdd59ddffeb5882b17341c3d6e5010943857fcf27eb9177d1d01f4eac89643c29832809590a087942ce309b72ec9743d9b2ead95830632999d0b23d5076b9c414827ae29092fdcd1a3334443e7eb4946f916c01f935ed2ad90c9791f24f212c220150245261692c3c674a1e9f06a8f19c0cd8fe8468834281f613085ec99b381a74bffb6ca2cd8c7b1e70411110713313f1d001cd78f878aef0f570dfd1ce8c165d3f2088c1a742e0018cc83b6b37cf9c2eb9af4563c051cae7fb9f5d9aedb516c2defd636395808025ef29c2d3e0de265b8c6faec88cbe1e1d322c7cf4d2f901f793d46762bd2a233e91ce0e7f775e765c68e8d5d3f840dda369c945c01c0d1e9ec1f4c9a2830b319aceb05b2739018df45e41a08164e69bbb37c1e9b22d6e0511941f889afdcb02d986c02f9ed82d8ccb94b3cc9bee7f5079508d65432d151cc7b4c40e3ac3928bc5e1d53703b56d9caaaedbb983ef5858050ed237347c3a0536805c06ae838aee568ab7882a5c373d8634803f950d9ccf481a4ba060d3ce2347b90cccde3b767bcaa8e3b06b314cb39c69c3504c95bfd16300275e1b5b3027f896349ff4b251814b462171fa7792d203235cc1ee5719320995c3d88068dd0b8eebed21533b032f57426ba12a65db9e2326594c76ed3470d0973f432669e4251edc549d8eefa2db3a94b79e868177ed4876e24adc09b41aeed80635bc0d101b75a12e64fb119c6514ecdef26961f07e210e1a72ccc86c8e5fd3e22f15127a28dda0078ec59ef3aad33bf8c5799c0de2b6c8873d6ff719ddc1c74ac99580052ae0832b566b6ea165a1d27c369d5a555ae8788011b36c8595e287545e9ede4201ed52c1f7dd087bc79b0f35b267b3fe5215167e0dcad1bb8fcbec9ac4726ff2023f9f12592a9817372d647d280e71e90a7d7c39f880e5bf8896c990bc8c4c291828d200153ef1ab2e400d5bf3ba3f60efd724ef6ea66c2c75390eafb1b77591017a187aa7128e77e15b9839c9115685130eb47eabb280212f9e8389b4e5d8061a6295ae85ee72c05994836f800abc11b1175e7e3ca65179920b4446192bbb170518689a2eeac670ee167d446b3819f29b16dcdf5503b0b42fb8dd28d3b3883f13a4bf36b2c9504518e63ac1cfad70396ff85e3b67fbff887578d81828fe5f111d7b85893435975b5674863b8a3f9a76d1cddc184eeee39db7853ac420f095170fde115a7b1b3a7f383ef87113a6f77a1138edec7feee548490499697cf599ef2335e6f9b7fa4938679371ed07813e058b91201a4848222fcc5e3fa2d797501a25a866fe0fdf394232c5a494beb9e63297d00195efb37074430e9a4981204cc61eef085265e8b8de1d6cd870769008211e165006e8b3ee5423bdc44e5198ff531c011a4d3bd57fa161a92ccfbe0d5597a2aafcaeaf6cc042b5cb79d47e4590012802357c661e7a87a56844ce37eac8a5871cb85e2f34cbca0acfa14f77566b9b0fd9a48d11b07e199d9d244cfecec430ced755a4ac507affbe74b4ef2ef252861219813dc856b9280a97a478755925040ac19e359f1512232e2a1a348dc4ab5b21d0953cee4b7841b5e6fdb787ba135d101ebac20752ccdb0bee7b8b8b59f4492cd7062b7535d5139c66c6380a230ebf3f61b18aa92d61ace15b82be68c445fa2b3a94148c49eba2a8d2438db2b33b0eb48f0f7831b3632297f29fc8413d0fd904a20d7ba25398186d33a0eeac9278c4d31547d3a8872e3bbfeead80350f62b30116d16f6518251aa9aae6ebad711e28f87cc9d3d0bc79e5abba9a95ed1281382933b1755c135eb4115630d3e4dd4e0b7ca034e98479edd3c50d57433b7bb0be00dd1de6d8e5f68454376add37ef224ca0aa7cfb5ed03018f297fd999eee543d21cece1629756ea5e93104701762cdc0a55b99cc72c54a23127914960a654dfa1fe4ee6692b34adb983da58f330e7e0c86ec396c3116a6e9caf0aa6b9d47737d05b91d24208aebcf80cfa68b31a98a009e61a68452ee12b07498ca5b18caaa5515f506896619cf48551316a095ae30a84e48abc0bedc74d6825aa238ceace417152211741dc14b488c6f11b0298d1e8abe2f27c2e135c927146ecdf7ac56ad420e36ec47a8279d5cabf88a0a360d43bfdfa43b9e891f5120955f2d4bdc121606227b6c15f345f9a55b233198162bda3808f27eff2ccbd4ec10a29d713465fc980792f71dfac2c03bdeb9988d1584fa91df81eecf435dac93f6ed2deb4cd9179f076f65880a7e2583a6246134e87b59fa14fb6d082f1b06b890b3ab334c87663126736ddcbe0ed487e975a29e2a5b4e80cf24a821f4853513b383113ea252e5341676f53cc7376901f1aaf24817b2c48267358897fbdc836fd4b02fe9e1161daf0850436efa21849fe994db36ff91a3ce2a677eed3ee2117094ed02bf47e3c88406cb6ddd4a4c69df5a5667fa9c2bdc3a6181ccedabd0420debdd15f1b163f15724845bab70224e26375714010772b3c3000ae68098c125ca95dd22805762a1d501748ba4623c878c2536d2eeca896267212a605808ce75b93526220c2c18c2fd0425ecfc409eda6e0dacc8de3eb8024d9a20b29a6fa6b729f72ead4a9f24c08812311ab4d54cb22663a5a82441ca9b84c95af6e6f0f00bce270fda7e439b4f3d15b556c175f8fdf289fe72668fffc1804643e599cab4caf6bbe7d660a2a1324f1ba66f87bfd12d5806cf9bbd3034648f277cac80e3dad0d4d5d065f6e5fc4945068922e07ca60e5b244625238eeed4719bbdcd8d868d756bc12a956e0efbeec00c1ab342d27f1d270498b2103ecae4de962435aaf88ac04186f4c8a3e2e71c2c09fa18c56627bc235b09d1fc39e214a784927feaf510c3c0414168f4cac9d6301e80d0b79b97fc8d550bbdc44ebf5846fcc340e67383c9d53b2a1b94586154a7267c1907bfe9ee68573ce8d99a711c9da911d795fbf0f087e362c461a4074a3a1cec33703aea1b12f87aad29cd97b8c0ee78cf8d09b2a1fc1352c497ce72aeea185431e962667e6a48126e294a1fa8028a0a135bd57068ebafcfbd589cfe535507faf50b320619186800fb993ea325d3d004d6b68be39fce6d70ab560a8efdab21c6195aa6cedf4ee61634f96862b7f7992e9df0fa250e0f25b671288bed15151d773286b3543c0047007a615096bf54ccb45c7da10eb3291c28ab2cfdf79e6027b2a9261c095c78470edb892fa58979c9880797acb8f09fd99a8cd441cc119d12d7cfd06d96edaada9aaa5f4af9e3bb5421b83f6664683c38fd04800d6152c317a0e3ed68287a4e6c0389ad3ee54434e948af4fb796b6d213911296cdab398c1e5ef689841cb2e4aa63679052def2edd541a376109970b874031e99609fa8f000a06778dbebf666f4e6f8e41ab20543083d5f506b7f88ef308bdee04766011f0cd392c11bc5fdf32fc7a14fa91c13bf3aa3b9be84d50f12d6203ba8408c630a1e06c80b74ed54aca8519851dfe341de87ff0ec0ce0b72dbcdcd19a5b84bcc9b041b2e04ec955f754ea52431acfdf375bdd7140f4ca9a0619458e0d197b9d572184832627fcff4170c1d05895ca491a09144c5209c6b0137a03579fe74b02b670f2b282ea5c15aac900a53cb60309f1540d09b393da213a2c6f949992404a50017cc3f11c854a7d4b9598e3bb233355c0f2a782c32b5f1b2954c206d44cec24e2fea355dc6b919550164a6814945664f397813afc2ee4939962ccf83edf950890f245df5fc5a4a027a2dc4e60031b93717114f900931fc88c43c6db6872ebfec1cac247b216f38de3af3895fcdef00eb6d9f00c32de74bc661e0b5b123448ef61a0b026dc0946b3abf48ef6ad7c763aae1e0162a13fc605b324ed9489b5957e806472b9adf3eeb35b76e109ef09902b907f8d314bb8ae5b00f35b7b3bd99320c163f1d0f7a9f1efa43b36d29045ebf4d1308cddc170acdf6257d668f89665ca10ca55653f44c2613af78e20132c2f8e2c7457560d670804077fc3b8b0ef8cad8188c0c24e2aac1b9824295e7f6578738378c55d654194282d186e7ad295bbc5d1f55473be32fe31a919fa6729dbd35c77aa45b1d79fe65a94b67bab20d47bab129de75ca256848e7f6a6cd9747d606027a2c15c7c82996cbaa34275bd40b9b9d244be024ba6672e1e7dd1dba510352a9445825ae47bdbaf81596048dc3a7325d22119dc8ff3f458e8c1b0a8048847417c41a7f6f4666a21286b4df234229225a180ae1467cc29b5bf788164e5c60dc9144bb4d7a03d9f077e15476698c7292eb25c42282e9fe3a164095d306c4d50583d0836c151d2e2ac76d704124b589e86128ac118f9fc484d30f6831d630663236b3ee425f34363d4138276c6b77e672cb2316d2abfe95a181ceee595ed6097f593d17f5f51fbff779e243b60cf18d08fa2588b099fe34c9916fa0dd0d1118f4512e362a92ed4459b40ac521c66987e8520d3e773435c7211b74168b52794532a63a88e72aa6b0f0d4c426edda82088bd80d61e06c87ee0577c1633d6a061e1dd3cda18ac626bf7912d994a48ccf30d1be25d3ddf685ba8df7ab532aade5a0b89f4188b835fe8627416d99c13fbd7312752061e846f342a0e53aff64ea450f72494e953f74c31ca50599a9d32e52ff6fba1bddbb5989abc7e68af1bae43168875468b0432799fe1adac2b610728d61ca900456a5cf5646bf8438251b7017636f3bea7f8627ef919775ed74205f1e93f11e1d347ee26dd72e31e5f24f8cca5f2cd905ea1bfcaade0ef1b23d0555e2b128e92c570745225a2f80506157bf8ddcf0febe3b2d3b87284803dd3762970f500a85062d89b8d679171c92258012498996642d9f32fc9b8914223ddf76b9228c6c852c41f9c81f6e1b8aed64a680437d2e8fc812468bd490c07d7d23ed50c0de821816380697a0f0c4600414df4a2cbed15eb6beccae630e87326898b8438ac274330a7009ed8ff4eeba6d0ec8c7f10a6c5958603769c2d49c3f451bcd83bec98172182bd68e46f70c6c146b3df9792afcf807b065d1df44b1d3f9a16cc3ed7c56300332a404de00cc561e8abdb366b02bb97d89e1783b88720eae99e715f6efb0dd1f16870ba292b53acca4709233394d4e830017a4925897bf1a7f3c2228723b6b0aa4784cdba6fab4402c28aeacad2b1ad7ea07fe04dbf84ec0350d4c0a38a5f22dd89059b1d89dc4854fbb17bb68850ec92224f2df873c113aab633d6229df860d9dcb5759cce6458d0d0d068d65f11061e7a66c552347b1c0475d3adf0a117a15c349f90ba7e0ec0ddd861864e843243d00205d6f7f784e63cefddf6d2b5dda21e60167e934049f40c3c334327300ae1fee1db8dcf91e861a288d5b8391d68d25ff8fceabc18168a51d1bcf6162cdd075f980301931a732067db196ede699e31593c56a31ca830f78c08d85f7d0598cf18df04d1a83744be91d62a9d48938360dddca24726e1709b34fa3089cce740aedc2468af8bcaee7e8e08d4a1fe2ff7912bbb10342e4f1e0449a95ef72f96f0e2cc86646b40d0b551593f3f3990a56812270d6bccb9c5122672ed5f45f1116756edc25b1053a29d63b0cf75220e817e50b1b594eb5ecdc079a8efb169fcc39bb820652a7921b1bb5cc9c4822a4a06aeb22c90eccf3c5d3db80fbb6d3e655e309c4f49e6c56edcc158feb0ecc59371f7d1fadd6dc96f1bd1bbea4fb37da9209fd80d90460baf6539345ce2f3c6c1f5c812074a5f478b326415d3f00d85e648be949a7ed61821b81aef07035a8e614d30c0a95c778b392a6c9117bd600c921f2b6b584595ee597384de21cadac502041981537a1874c7e2892e52bb994e8c3f4e7daabae54a530de5402587dd95a740df90c5ffceff04a2316ec2e79178ab83c9e36da6009e8822e048a0cb4e3ecf78a3d235ef3d535547f3823e356568660deff8e6b42ac6d603904f28afb5d089863b405e9f4140639e2371bf0b03d30c41928a0f4d2899efb2079fa7276473d48b26611221288b65b272f62a9594276fdbdfb7c3a75f4280b93afc08c79bea215702d1dbc1bdc87111e706f693fb3d720a0f002731f7fbe7336393b8816aeaddcd9781febf673d810faf0ec607e25e578ce30710747cecec39c45317a4cdd837e436610bdaca35664fe436bc093db244077fe02b795efd71e140ecc03667852eb3af62f1228a2ceb412f361e3d17623d587eae378b63b5f67a2d6dd0f63ff41fb3a0922e3f22c547f8e936f3ba7a067d15d43f8ffbb69a613c78ba56f51d9345c54fb15228ef14f959b31bfe59542d1d96787d1b10692ee09c48208ccaaa8ccb67df32d091bcc75cfb8f30ed28bee0d15c0f952c97354709ae4ab77dd9fa2ebb897df2ee1541b7328936f0644a69dec6593585b86c3702abf0cb12d740361b0d7d7232b730943361923d9c3f47bd914be5e4d06202656a3521b75c1bc358394e95d4b283da8b0a31a6a8acf838969ddb6a54dfbc585bc8871a31cea3c2d0772c74984283dae9918293e52ac715eb27d8ac775a79fbd4b0b0f81a3c66c44b92c05c3812cc12592cdbcf2fcd8ba7621200be3113f36ed110e93683de0c4c0b88c66efa61bef685fb8c17c46ff000c53232380be681a24affa72d07ef36e0ae5c0dd3ea616ec94567324fabe7332389502a67299e45c203908eda045ee73b927eef6129e17edceb74440d44896e348602d32c40312a7cc8fea01c0bb61bc870ea40263ea125d48adbd62e87b1d254ea192e3281a08567aaf8219350686824d19e74796742a05c1b82a755458b9345fc7ff8fd009630e1d46267874bf79a88eaedbdaa5e61e435868e8aac3e2b4370a8f54ea37a111c325f4a07dc39ac01746a3f98e194f0cf38a4652916baab0771f2127e9ec7791b0e37b765985c5f0d073e42154851f1719789e2f4de1bf9b8c3d81849148b1df87eeedc3d6583cd994c43071e6eb1c0150e3ca9f5b8a5f962ea613077421a8f906d4aaa5dcc35c78ef6d8ce46ad33f", + "public_inputs_hex": "0x2138b0022ab9af3c96b082bbf307bc9e79f8f1401462e3ac1cb3a9913a5b856c18c40bec999a837ec1f06dcee05102acdef50c501e771cef739dfd0a4cac5e9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000211521e0a601b59f0fa9d199e9f861874db5d701a0c38f6d725d9fd8c1f0b53da03219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218625eaefc46d4dc1d14d29441b83268d90e246af546b51272b038fd206edb2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7296995105557a58df75d3a42759d29e124a15ef43bad6b7fd6a9d93d4efda1c900382d23bccbad9ba827179293d23b719de8374589fcad5bc6d2148bc787593a" + }, + "decryption_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000294fc7a9da860e0de000000000000000000000000000000000000000000000009cdced94988b65ecf000000000000000000000000000000000000000000000004d00a28a82c32ce5d0000000000000000000000000000000000000000000000000001fad828e01b9700000000000000000000000000000000000000000000000c0ac27ebaf1221bc80000000000000000000000000000000000000000000000033e0eafab14cbec0d00000000000000000000000000000000000000000000000757cdd9da30a89f350000000000000000000000000000000000000000000000000000205d55489f97000000000000000000000000000000000000000000000007def0d56effcfcc6c000000000000000000000000000000000000000000000000d838d03424697d260000000000000000000000000000000000000000000000055b7cae97a5e905a70000000000000000000000000000000000000000000000000002d8175302221e000000000000000000000000000000000000000000000002d7bc900bcb74da7f00000000000000000000000000000000000000000000000b8c40c16d00c8a23a0000000000000000000000000000000000000000000000013e601e60b676ff950000000000000000000000000000000000000000000000000000d0468cc026ee2459e202e853593058b1db0784b0ed9b36eaf47ee9cadaa08014bf4d8cd3185a2f2fe48532a9a418b29e10b078d3695ba07dd25f5e725ab90220be9ec08687951f316bc8c628606f4298833fd7f9d2c87ea17d01b5fec6bc88ff5919e022391427f7da7bfb75bd26d4480f07dd2369b222049599bf23e227c74018706718915e1e3c8e290aea2380d2f1f59432320fda6a7528328dc891506ea8c73c0877633a237ae8e7ecd4af3e7214f4148072a8b265521d50206cc2e044ea74aae7a67d1d2ddf31fa3c5c4df22481e54e28ede606388e074f21dfdfebe4236a36d36636f3158452502158f58655a3c809c0ae7ae640f43eefc892187fecee43c03179178f04ad773d57f57b4a1b19b4b5c362f5bbd0756fe0fb35313d65e4a6f3c2bbe6842ae28f45b8db241520425f0ec601491d05902e4ce8bdea9afad1f6e468bb39eb2cda34d97fce91c8aca86243f88b865375f479831ca9bb80e8a763469dedbdf92ebbe029e22053d8a32a6d42d9f14cf1d52b663c7fb344f9310eab3d996d6878174a1ff66145793f5a9a9ebd7a951717898cad749fcc7a3006bde824edea17682b37e47270a2bed20f65231a78178a844ef051047364e82a31adad5516137234247998035db34978941f97a592a64654e078b5acfeaf9f5e320d0f18e51c25531c32c6c557ad2f11ffbddd2ea82e89f58d036bae5c5e63e56bfcc1effa99e9d81056314e8ebaa1a4aad6f150638427e469d50ec5435e444f96e5a4f69f34ae42217aeb8185218b67e17ce9681eb4e3a675b2f2f5b4f0f15c7b906561ed7fa55810f2a840ef501bfbadca630161525a3f54b774d877dc386d9fdbc10e2c95a83d18a0cf0c5731d507ec4e5f0f867126444e5c9510794038b3d3d8831f09d55af50394621bc1804b8b4583f3639687613e55138bdb626de365f69aede7048165fe23ca346dda0c5133017abf93d261f82c83099c2c33a8815fe4f092e2ef49fbf5251702d2b6ba4cc3b0f675e38bffc71ba88cc9838a207f844154272c69b01f502d672bcae5907e22252e8262ba05b4f5b7b1f706690f28650fd56e8572d8c7220d132fade6944cf98739494d36ac2e372e7f1d5a4a4e7b8256907b9472fa788b153d4f292fc4ad888ac658e37ad6e85dbd13125f36ba6cfbcfa9dbcf8e4361a5025de0a5ad4ab5c598f2697c534de6914c1ab8f9751d5d7b2ae666e5a65576c5224a88599738d6ed38469061203d645ff172ddde1638f08da2a3bf320edacfcd22b780255c9857273284701d0403376ff3260c92eb9e7273020f6473712248bf1c43a07dab1d32fcea48bb38a41f1656b5ec6a2c6f9670de2f1b60d32e9d7b7227c52778ce41c42652ab58a56904946766edd2eb19417653ebbf939af4dcfbb7163359c46e9022063746940d4d7fd8fb0a62f0826f29898f68cb38d7a0177a5e21cbfc8e122a0af6557c749be7e61939da64b69c7e18000df1cb10977b08a1fa1328ec0746fe2e2142da4e6f9f279e3962a4d80151da3b2c963d7007fa7830230e24dd7805f5ee35897f14f267cfef072a2a7d4d232141c32f7688e2bc12ac982eb506295afabc4d912d6fdcd7c96293c432c3d544bab31a760021260d3edd501b2aad6f77daecb13cbede2301d0fbdd0d3b3bc5c50999fe8fc82af9423c4d9c1a825c8cf5b9b204f4e3d1f2a831fb7cdd33a69cd3afb68ab16a16c3a6c9643f1a408c9e6f64e50245cde76c4aafd47db8ac2f5bfa0cc8f4bd69e082b66e5d380800d387ba9c41fc32f3bcfebc1ffdef85c488e25104c3c8112540af09d0112c2e6c8aa2dd27874d7774b1ea21dd1b54f3c1f9fdced53535104aa0bfbbe49c310a9880d9e7cdc46d6b7bf4609ed6aea3434e450a3fb8be09a879e60e587479dc053dcc5798759ab8f96da932d1eb7cbfa4adf192f00dd167aee524e3329fdc4213d648dc03c02d6a9151ea566a0cda04b59b92b21f0053b15511b6378fec2feb119eea1ad6aec36c068dd52f773c1656b9794c65a7f723a3938dd4977c1c0d3603e745aab6b902d46834b2820f071764b6574fcb80db1c9f13b73cfb6e4b292b2ba0b64a160151353d27c938e2b4b18c5c9ee97e23a3c9a876fe744bcee41fc225a91e7ebf32670753e3ded6e2e9af3425ad3e35e87975ca2c63b2f6186d199b19cee0b57652f3801788cb5f9ad4778acebe7b9fdeda43db9c043ef4137a5b011e592540eef6d70d70e20021d5eec3ba03672e8dede78072d065ececfa35a733198aaac4cd5d63428f39a8e5e21bbf16c50e7e6557c8aec4e0da20a36bf60720056de3908e28cf7581d48db03874f6f6916afe7d0cd3309d4a52328ee74613ca0abbd999c965bc5919e393e49b00467275c648d3ae08d8a95ae793364703219e0bdcc6722159598711d8523ed03e9297bbb79aa6547dba65eb4c35da53adadfb246b58d195676d5b197da5345ecd3c9d523933fa372d1bdfc7b0e3f32d9b00b005f722e8459660830d6526efff66167c6912c7cc6cdbf9efbe76be95246b5a571d8f4c85b490b83f320d3b1dee211a8df62129ece02a51e15a85ca6fb9cf575f24b4cd1b404495341040be48b09a293de2a47fb3b96fae5e6404d0fa80ab4752007b1ee2455f3cfe81f8a0196925fa9fce41611fd8db8d24b0727560d9418eef2209e0ca5f5e3c8cec70623831428d3c400767faeb6afd01dd445b040970f61f17a7d3b7d45bc6005b2ba45d69902cb0052c481b8e77714cafbf97de9b1d69a80f0424d92f06c10e3250af1362c162487b277a6684439aa4ad6cdf6a3bf22761231b27fefbfde64c56f987d91ac5cae036699a100e5361f01cbedde2d18c919e24c22e8de03bab49e04dcedc84a3eca8530c23f22f344ad3f97840b9b18a61e42e1adbb61e311527f8cd6011466cae22387754a8347c340c4cf1cd4d3daa44630cc342d855ba56fd02dd12ebd4beac7623f4d8423eb3abaddf087abfc4287ac01018611b6d426257d5658cf92248dd0519b0097f1ffdf13d114e1a6402b4ecf91f4a331ca61974ddc19623097bc0fbe6f8c015d41874fdd46c4709779832b9a21659c619dd72d147107def203ece56450a8cb78076083d47dc6d5581c0e4261720106c2d002246ad9edbf060db3a529aa65d95e41286165f54e341de6619286f11071ac18276fe5e98e6097b42d4a45bcbe496f88bb6172c031f6432f07bdaf8291b40a45182a9ac24da29515f13705d518802bbc5885395dd9233d953e9bb9d290d91ef07cec9a3de38045ad99a1b7828791ff35660ce77a8848dd1180b472b00856c9b76a8e7fdc5653efaad0154b023f8d930877c53860e3afdb8985a8d2825c2656baf2fc91e8a295b7fe091742c01a3c9fdf5593e74bca97434ec6cd1531edf169b86a01057d936d55f95b3571701aea73150654ce6cae2f98fe198f9832cf05c7c4b579f63985db2581fc7af7ada21d1a6ecc2534ee77b71a9453f7acc017982bac86cab3a4520948f894551800e6745ac5397bd3af021c2ca9e9e7d4501491d40f0262528ce14e591506761ec1f1b04a4b8218dc7240de57c9424124908ff18ea7907906defc1dd158413cdb5e6caeef68b945cefb0c594e236747a1b1dec6fb2c44d7c5ce2a82dd61dde2f33b5a68855602173bc1fb3db2f2a81ed91298d4736329e140e147493320209d367b33e0a638c7827aa2aad48ed8273c3bc0519bd5e4e1a9f986e905ec2a1caa2903929fd4ed46bc7969757a46360005c122e0acde7ee62766d37ae8a5f2e4b547e89dfaa316652ee28ebee61ed6e956fdf052a556d5531ce1e88c4b764707f385139275e389f61e5f89b98c662e5ce990c10b491a61a4e90b0fa60a4441b855471136454e47ecd23d896c6bdd5f09e718703bb8022f7d8647ed9c8156e253458c01648f194c62af28fa76002d10ee418d403203985ec4066a71034667f395f24150e2ad69ccd6231fa3130eafa0670651e0cfcbcec847b040514e9e552d05b09dcc1eadd6193374d776b475d446b1cb961024cd1f3ee9bbf2fc7ade6a6923c1f3f77ee63afa7b1dbf88e0f26f72973cf411f0912f87f18d688280040c40934cfac69db7b0bc9e2dadfbceeceb5d68101e62c279edf9488d4e212ff015caf57d42687fac2e10906637225f287cd50f755d628b5c33d276e3a54de8d8a0a187cf0d41c3ecdbdff4db32162535b35eaa14e592e022ff231c63501d7f23f49b905a607abe8fafa9652522145449f412981d4d60a9055cab29ead09f89003ac2c1c78ed5ed99adc0012318dcfe8d735884ad5df0874c62cc3404cd9e8b614d30b0145e71c58b665c0d2fdcd725c862a6e39ebae0b08331739e0c419afb6f8bd91eaa526cea65f02ee0d5e5a6356c7f43f3ebf932f159efd7d59300dee06c8bbbc756d846f609ca0770eb0402564c490a9d350ba11bd5e5b2e464e2f8d5e7943c93e84784e750178f3ad7fe184aac2bde41f03d2021b45a3bec599ad5cae13e571aac7d3bcc64bb1270f8115e6dffa26c202ab6527535fbd96e3ee327f312ed59b386467002e4b4f45c4b2ac2047e7962b3c8be217298a2626541552599b72662f0569a7dd07facb14d6d5549ac8c731ed8082972ce63108b948327d33e991f9ba410608e8554f2a7490a6bdf46af259bdd695082df8718872508971841634faeb9895de0d4491f3e2017206c97f319a8c0a6e4d1c85cad433989c91a01bae57ccf6ec8940a99850e661caadae51988730fc385229bcad6ce7b97a0eadbd48406b5fbd2997e41ddc2a79ee8224037a36b7cce175218c1c06fb11cd4d271d994ea75a6c4b317b1ae0992df5f55183de4697818f6b13f27ed893be4494f3e90291d27f19f89d80eadcf8dea2145bcbab08b546c8ba194c6cf80a97d4cefdbe79aa1215d6657894192b0216324d652e1d21e124a64821d4ab31faea2074e75791fc017f84acd450c86dff047264915bcc896c3c543c2edd149ade794ade1f7994d6316eddc373e183d6067d51b72d228ebd6887162b04758b45e2b15631a42421c06cf2775240ffcc351f9daf0b357be8bf7afabc2b1e93f729161a1e166ecf00b2623ce8fb94ef53bc8a96877f34d828e4f033e4362f1e27ee8d03cefef5ab49c44a121687d7c7d245efde0b97cf73bddbbedba45f2ff6bbfc4172d84240c261bc2be4f749bdc75e17e46ccd3675bcbc201c97533b111cf3aaa5e460acb2817cc870eda8cb16ebdf7dc00cce816b3574c4818b78bb1d2cee7efa2f46f9e845492d83a5c02e885f2436ab71ca2a2a224701f583fe6026d2db3b84d0ec601ac908afaff0c85c23c705dd823380cdf0e081247d59b1b60c88fd5a27d6db83584f5b89a34bb35d4c35b96106ef73d15ae819fcb47ec96717e5eaae59cf0c11214006361a744d6ac7a25ab5e77f2f8ffc2fb929f60ca0521d3d5555e8794c7977e5f2c3f82566a0dc3b02fc334a5ece8b07c4dd72baf91f227a153e8a11407b673b099ed5a336d10e1ed0d078377159bba4d50ebd0bcc7516c2eeb310e1cd867bb3e48a009ba73d9e0bfcf4e3f09640cde60b0e5923e6f7096155a3ad2a98eb2b181b6ebdafbd076ced5dc7a3480b10465baea717e6b61f293e914219dce1f1b876a424818aef3c0e7058dae0c5a2d09915e076c2142f1e08cd631d377737ff19299dcf4e7ade54fda78a166267ce8c1094a64d390b8dae2259b6e601cc9d235d2914db51489547d9ca30a8c2a1ee2e731f1028564d14f4056be7c0fe8eb2ffe62a2fb7a5ff145d688ca30a27f5dfa85db0c3aa9a860aba12a1b7d5cfb9689148028b605a95abf982a4c8d4bddfe3af32e5d6f7b26998be18aea5924288152469f17a16a11660b072c5440053e6ff8a5959017dae30c85e13523b6fbc00afdaaf2ff8c1a16583c64e6e1bc4959fa154d322c947d0955aac28a3b1ab3eedec9ee7ed7ce944f7e2f62e2c48c22d5592dcd5ab0222ac56441727ec263df9bbfcf0c98055df596019ec2ea30eee2b704346cd7897b10938666b1c4d23a603ad3668d3a0d7fd8639adcc00c86d35f636323314dc4c2768f64ed126b0a6cee630f96df5285d06b336f819433f242f2cdfed6288a139b06f7cdcbd11d13dfe7fb8178badd5c625b0601f1fc05b82d465ae998675a21a119a67fee024db3198472a84885b5625d99d048f795646ebf141972dfc2ae6b0564fe8ccb7069d921ee3be84673cab69e2b5377767408be6057236e471a0987befc554b25617b1059a8bb91e37c219f3cb58dddc5b5fe6034c30001e70f8348674a57a06372b865e3326ff804d8d31f229710352350b0b723d51d760febfb162c675cf34ab201ee76607ebe71a1b46136f68d568cabb46ea5ebf5affbf919c375d38c697b20b248f0fe7206cddb60b9365cc053a13e2d6586790947ea60bdcdbe4cdbe65fb03053f1ad5ca162d49cf0ff176a41101c959a27cb3202c913a668fb3db3091f40684cc1972ea56baa750ade20ac6489f1d82ccf49ae3f850fc26a91986a46f071c3850f7e561f7e99c197065bf71d303f25383c380ddf55266585210b53d36fa149a217ad688dcf0e8ecccf2fe65ea3fbce0250a65b277ce4ce3cac3cef0b38c1c28e6dfb6715f3c28f38040083be9c37beee26aca1200ae15a34d9490dcc5412c7fb4c25ca64f2c6d07ea3b7a4761af12d0f5e472e2081baef1f882111de6831bbb4805bcb6856144c55d7f239d1438d8e0866135a6ecf5d6ff5bdb392ef4261a24ed4a439cc079330b5cc78e34a0efb3ca6a8ff36756b253befa57238876a02bae552b5d9384dcfa2d2154d8d34fb5e0c3b87220792b9c408ed648dcbbd4aa04ea3a463d76a49e365d7367f6f04956ff2702bad4f9cac463d01b43dcb044cb2631d73967b28f9c9da4444f03556276fef611323387027818cebb63b791b61f0e98d4aa94a4118674aa11a5219f1710a2dc474975ebd3dc436b77ca2c9466411c03502ad4ce5a43e3e84b403e745be5b3fb4e8d3e833dadf73889b1a850e031115577c21a2a947e88e663b32fc89dd3dee7fc04270ec0e98dd7ba416b3109de1981d92f1918ad98deb2a72a1fb76c053b187103874333f579d5949f4d20f1fc0cd9938f737539b95565068f672871631909351fdbbc8e6e3880a07a259fe9111b2510551a619ac11bcd3a7f9c8bcbf57da7d3a39c3c03183b4386c8578ee0711be31df13d599e5f1d1dd6c3279ecdd464ef86e94b15a30eb21f47a60fd3ea9b2fc64ab168b00d7d3a5aa6d35889a614b9913222bb89bb344c6e8fde590b413e2eb668737bd00ad942e02af0ac0f1f8faf0bb6a08cc08ba9c78b2c293e4cc0d62ba094060637baedf137e4d78103aa629ab3328a3b8adcc1b62fd06027c06d68186fd2e04fe594bc699eb568edc8bb90ee3aece987e5b2a2018089b5ab1ca2d619ddbf05569ceb9d23e1f1fbf61690d3d2c9dba88e27d438d84e4bb17cbbe3cd1c10d73d1e563c8bae721678c7b22d9bded93aa4527f2135678dc198d0005c5921a7b48aecfcbd1dc92729f0360c33cc9ad7b581cdceb7b38bb8b9d822bbb04402ec2a6d3a66616c4ff68d09bdcb6c4334089dfdc6d3a63155be13d61023c28c1ca88a25be0977971236b26635533eec64b627ce11518adc43985d69308910220c85bdef91505bba10f99919a6b5a14b66a6a065ec49dc998e15b064ad61c7d527411267826844692b4f19b8f6d7ed2196a25793a9aa1d513ff58e78d98c1343018697653c8c57a4798baa88cf2e7dbb3c8ac5f625fe8b215c8c772b99ed92d11258580d1282842e8b0f4035c42b4aa5f87fe6f03b79ece85188db4167b7fc2c20446bf66291fb855a1d9a39de217892b292f16144567957c879fae867d1e96215f75c2df160eb373272da4d441ace877bcd99e2ba9e917e4eb21da3306461710932e3280d8baa624131c6d7207629aac1dfb7751305c97ebddba4cf32f505e92d1f7f3417d2a7c7e0f2f45d2202ed3678bc7b950c2046d044980fcd96c1988d10841c8df616fa31ff7162f82167410d2e8295324d39e42e3558654898c73a082003305c12c89396909e6197117db6fbdd22ed67683083da843b1ee5c9ab184d2a1d70e72b415010e22b22000e198ffa8fda3d1915b88ea4be61fa078d9935d2162725a2b75375cfc381a35ae2c6cd7f7f37a232ca024c412d62410373d8f3d41f1c246f3f9b262faadbb872c0eb846d8ccf186a4972e040f3c67cd894e8563b253c08448b39eb88cf2795df514fc9fc043a9af9b3fd443b155d1c4cc4a02c1516987105a98fd4030fc588ddb086f85d0ef6192fe60e5ae96c8fd6f689a734651db0ff009896d584482f6fd532192bd37a367f2ea8f14f8e14f4055b5f93e59c07998077b7dc410a221d149ab6fd9d7e2f39e0a0318f7692d6246397f5e28d343054edc207b0a109d96752f1aa2e515bdedbe66b76d9ba686be41ba1b7bafbcb10a55c6d64a7332a53bc5401142f73b7312183a5f26f3758b959139a7dd1c77f190a0c1a62ca634f5d245a22f5259307aca5466dba517143431d319ef0f17c97056e143a60d54b4012c3899063c248faeac331cab5c8d52d2c7ca08543bc969018171f14afd40579e2964b1488cd72db78abbf76c6420c7663fe333988fad74c16d15dff2e0179a13f6482a203c57e0835b1292c7e9407e90cf1c9b6a8e925de2e94b23b556f8dd517ea1cb9dbf5b8e3e7b37a75825189bc2da93d91d0d4fc001afacb8a9aee19407d04d4ee0a87bedc7814600a5b1ca5dd2d9b763c9571158c17792d3977839b67b78237ed371e433ef51746becc410f8c4c8ce8fc75857568304505caa527679e9124d3b950fc34a358d86c71c488e22fef5b9f13ec02333004ede26f66b9dd31ef5478bf9d9f9a279db96d2b2798ffd90b9f88073332de6321f13f498bfa24c7d7d657a3699e8a456467221390188cf127b034dedd88e64d1c595ac1217a335bfb7e1d136f87acae17163dd81997997aeec86c8510f4e6a4293d31fc61e96dc92915917e2a9479b41f1312615015ee6fc99669977f2bf62f0115f6f2fead7ef0fcde3199782d503e25f064d42968698d18cc5faf2dcd4c820b6f4241eb0d8fa2d7f3a67f37b6efec872eba2f121a8ad6fd19790a9e81a1012fed2cb7a51927fb055fa243ebacfd9d34e263270da45a07d17ecdfe9e8dacde119470e3335af87d13c2df1ab37bdfee41ef292875890513bd2d054afe9fba3e2ea0a5004a585eea3a392829bbf9924950e1a8f19c8a89bdec7a4d79123458150a675bd0086bc0e606328e1b2d90db66f5bd09b1d0d25f1c23d35dac4e333daf1dfc2b86593c87d7da7ea5f0fc7b2d8316ca6411bd33db11bb20f4e1e7f722401a281d0ec39ba92fedf74ac289c16c39ba916320b900112763ff4cdef5d37020223e1db498730bdb02c6af8ebcefb5278757ce5d6cb334ff87180a23461738162d3051373c6b97bc861daf86b0e81cbb150838618a31e9555ab7e4131a787e5a0c45a10801285cd1304386aa98dbf01a5414b36e6470c7aba836ef357f59d8550268c93f11cfc514093176f596c163165dd736b0272cc9044bb8015d0c06b63f25294a68ef20c7aec7ae1c8ea269751ce4b07c62cc70d0c10c7b060a8629285c0213aeaf333839e428f8350f838f2cd7a92dadde11833196a80bcb361ac6ace41c636b29633940b14fd309f235c195096780167d3d7f61675799c574ec8f87630cd68f46920207719aa96180053eb7426d74d43b400a9bc9635fec645eca84500853823429707819c2df8104d1a901baaaaa82db848bd9c1364ba031eb3634c71d38ad5910831edd84d4c557b4b08f1867ca289c598ac07557c748ab5feab8b82473dab68251ae7bcd7c5647c6d5304311af4486e62fd323c142fb97da8209002da62d0b9c4e83c955be1f41b00cd156e8b8ad42d8babe671df8fede1ee503232106a8069ec3de80432914f60836d20137ab8fccdd1cd0d517a83881d7730de622b7780ccd4366de12bfec1e8c34b0866c0a09ad91ba0e824ad360d821415f680c0a2befd66f5571e8b41772764d328c7db755693d38f27a22ef31ed4dc8405028d31e01fa2652b98e57f431296888f183f6f5be175647e6dec4639d6db8409f1d8c9c029735249ac3895eed4874b9f44bc2af56ebdb8b0517ecdb69134573881a0fcf9f089997750a924a42a58ee70848297aed999ec8cae01e0817db88060e0571ad7f04ec21db8d1e09168c00ea301b237c67fd8a20f32312e2b08cd8321108faf25ce1c6cbe090d143dc20031b78b474d23d16066ecda03739aebf5679c814569ed46af286d8843a6cc6695a80267812bbb4a65b79e36ed365a6e7f38e3e0be8ffafbbe19fbd0f8d7aa7c6182f34f7a98c09b3c1fca3d8c3045f371b2f67251e1ee8c65847410fdbc8c25a8911556b3120221e42f826aa3f9e5494b645250553a33a5d6dff0d923ca2a72822672bf340c1f2120f0e23bb467241766b42232be23e92fb1908df039216ba35db95711df908ab6485a9bba4d5a87bcc4bd05116fd96d22e85e5d6c4082bbef33f8a9599f096e26d596331432b8c961cf9785b0e387d9989be6bf719b761cde20ca1c281b3a701fe1073b4173e2de4194cf8822ad8b7de42b8a338b81fbddcf7577883879b32a40065ad0e2a185a7d16b27130008b65b216b04481466561823657bcb5b911dc9c2a401909ded3c1ecacb90c9c0a3cbfcb83f3ce16e0824806dbc962fec61364e37a86846ff10f34d56114606c256ccdb004b77daaae2dcca4d0b485e79e85e0498f22d2b796a589fb50c656bf1d3fa8227361343d20567a376fd9bf75788d4c2c62492132e9c8cf8cbe69f451062728b673016f2a3d4eeadf5b45c64d3495b0745742aa9c3d967f2f45a6b4062b87fd9b08573a0cbcc91ab6fc3a1edf2af377640fd7da945d06d25de440b3d8030e1442bd08c23cf8c8751ed57bb44d92693c19a677d1dc4ca5bd1a8c61fb350a9522d45fde3891e1a4e42d65b3cc268bc5fbea6be51cdd625b0288b4854d232b514209b5025fc499f2a2dbf5ca9b4dcfa86adce2c04d67fabdceb651fe00f42722a0efaebeef556a81bd9fcd4dddd0253bbcc4572ad366a826e7809bde043e2655337bac8a5010a8e47cf362239c86eba9fff5f990cfaa3207db96c424ece11284e9c4cfd5ee0ffe0cdc22cb4b0cb4f0497643ee90fa455184a0c5445be0781fd0327a4f99abf01978729a78aac72e6bce4f800b2c161fd520ece0c247e5901f54d65b211f28497ae07bb3b1f9e01954a9f5992b24811a107be00011a26dd0022ec83d890760c7c2ba53b0d1814a97820ebdac057be4844c0adceec2d1b167100cc4b883042951639a04cd145d12421d5a8981445520aead1ba5587f6d84ec05377554914556fbfd22bc791426acb934a1c05b9db714c0f5e89783c25634111b86469c041a12d6c754fd275672ac4fd7fdbc9e08a52fe330be346527bbe81503b2554114aa2257af6b19f503f7b144bfa04f009bcb8775056abe574f87fe130847581f87b3574906829ff45b6261775c4d4cde8a8ec7d1ea9ba4266da0249801f64f47b80cd82f1fffb91355ad5352bc6721be76f85afcc95cea9e915e42751d48df16425f7c64e51cbb16208a865413c00e3edc08e7664a8dd5124fafcc751a8b758727e3949eb6e998b4368e0516ab575221e76701aec8274230c792c222217fbb799ebb55bf323c1701fd082d195822034f84c0e328e9a59d7cdd54c85026d5637123848a858ffb1b15e38a1dd075b3a459825a7a28ff99180ed703d79b1dbb81194e04b890fee7b8e3e83368e2c1fd9c08498533e1659edbb95b95212e216fd62eb14f71753e05ead6589239ed51b459731393dcb773b2237854c41bae1c16cb6c4bb645dfb574de656237a7296ca9878a3673ce8990bf543b9d0c12ac1ede30fe923c6d20be7662a0d0e4a38adaffe36550f397dc134d016d8ff980100502b0f39e4965023b7c3b3af13c715c27eb92f52eb1d1ea03d1c03be14f60ce0fd8e4ac03f939b2ce46c0a01edb02f25ca0c0ea42f9dfe809c092557f31beab22311d06896a390c81ee29d9e04cae3ae900307878f58bbf25126d195e38b426158483c1f1e9ef7c902e4bfd0f9c55eec465849e8528fa93873c49eb507376b12857ca9dc18297fba6ae7a87e869dbc2836eee0d87670f4fa76a4c34bd546a5711807ebe17933f1d48bf83fb802743657e432655587833322156c82a0e81ca7a17c494b8d8caae91918133b56bd5a39b8cf1821639be28d7ae328843567c448919124d83648063edea2c82a4cdc631492d0ff9272c3f48e6d764a37eb46b0fa826c0d89d84dab0329281a30afc436a38501e447f405e2228de9722dadb710ee212f5cd5def856e1620f452f1b1c87c99accaa5a582568ec5bb2312ad3507aae82c9e51477dbd662726c68b2d14ba8471d6ba3a99441a3ea0560cc5263b0f729d11963af53bb44db5f0d58d430a82ace1bf46f353ea9e7773181b2455477b81a324f6910de1a2a5660ea5ed1a2898d690172d9e6f112dba6616af5750ccea74c3170577d594c335a412b11e5d6e6ed68e121b7e9cf290da72b97e1de4f0e5b05e28671d66e16b35293d9661a5ec2399e1b3371617b2f081c3d151a93fd9b2765f05afa3f9c804a47aa1bc5360244e072115dcc757cd089be47f94282f4ea347e417a7a09caa4e7b27f26b077d78574e929c59fa46bbe952386998f4b801b1c3741b97c4ca89df3be88ead778f1c1a6b8acf8d89ade02bd0f4087014038b8c603914119b4f1f2dd85a60ffed60f077e185ee096f503ccdcbbc4f7536c3a40abf942534b3129f2c4d48b1c40cfae6aefc3a1fc4edcde068812c95e4346ec5f3bf792e7e79b33f5069bf3d3a38f9cd0e695cd8d7df15fba8820280e37dae622435f1090c6aff3676f8f9c6835b12db35f1dad19430632bc48190b3820465f381d19c0d25a225d743b98e22f896675ddfac868a84c10de3c08bb879ef68053834b75b209d7d2b5b940f6556b33db43abe2e7dccde728594d43e3b3374cf51d00d55301ce63c7304188ec2d1dffeade768ba841f036195ad0a5e56d6819b5bfc9f1bde1bd6273e3067270b4952db3180d3e11ba1fbc38878b57e866066ebd964a60315021dbd9f8ce7615488bdecf26732a657a97121dc0e71b7a2ae9bec2cb1bacd470d8df4153ccd25314e885be1b61a84af34d7b9c2bbf18f632c81594ccb92671a1f06991ae42cd0efaaa7ce5e8ff8420be51526fabaf3eed5a4bbd76b5936d8ed1a8cae7a2a2a073a113a46f6187225ed841a5892e1c259d2fa85151af18dbcb61157df91a0106871694db8b21d2ca384903fa10969ca1ce6d4a85116d39a0b1a2a9c5098a2d510c6ee15fef9ed61bf1d7d2df7673e2dcc3a37bd4beaf7344e2c0a1f01dd0c6bf05c58d82e33bd1b8e50c9dfe5dfd28381771f840f8547a4ae97205b2e7b0feea00acb07650f886ed10719bfd7526b1bcb47885df11adc720189102366f087659d617efeff715f82c271c6faf35ab3aecf3af58e1f1d507dc6fb2054e65fc26d9ce18da03336cb1225e3fc9a742f9d4dc4d31ba0b38f98fb4c8f189b5383795d0b94489ee507b0910d167ee74c2b9ef6abbd95a63574ebd307140efbae3d59a47cc34233d214c8206769385682b134653792796d0b7bb7c9725019323f9803851b4b82f4408771caf5f32c4d820de1254dade69f986f72ce655104e396cf61b531a17043b1ed61c862c4557295a265c55d928721ea03f26395722746881e318a3247a67d991e5367c5e0d27f763c0c8b9ae98da21533b9349bcb2c866e8d6c2817ee8c289e679e112cdce2630cb4659a661765b53da0f2eba019113fcc5d35042b7733dfa1a0f4f4293edcd7498a59095f0f7dd0f69383ace4e70b94066de05000e457ad0e847480178076c8e11fd59c5cb2f4c4ae18cbc29de0127beb7f7d09e4e70a545860998aa357c0a98a930b17423de09e9bf2c836975a04984aa1b23e15655a38d46be2fbbc7ea8b8e6ee5aef0aff5defc62884455c5d28b85f4141cdd20e88adeccb3036e8231e61f2fb2cdee5b76f36db7b563ac44116e5782215a2dc315b6036a8b5479041bbe9d284febb79238c16152d926176e9079cda4a199aa8e2191127aed01772940f9bde39e9d679279a568acf825c9d872a7e64627d6d4793cdc00c4292c8b22941e40679d3ed7242ed61184f8016f4c91a77fbcaeb64e9e2276530f3ed9c53dd57c6b70c5d532919ef31cfbd6cb58d502f92cc48f7a440dfcb3f752bffd5707cb6732b31d9a2225c0293e7518e0e771a0746565220ad9cfb9f62a650cd9ba4eadf536a24884c0e238a211eee9ff3b18d140bce6ebe903302494ba1111c23946be7cb07285132dac658da9743db03c3b912afe729d887514c0949f5c2c764aec634511f650bec1fe67a065de41196de460f2765a27520f6499e447d1668f5b9600b213d7e145f9aaea45f7e599970200a2a86b06625571ecba20e1d979cfce0f298c775efe7a4be1630b9aa1a6a5f3c6523c4d01ffccb6a01c38123d4cc75ba480e9be9bf46f1a43e2e979b62fa4ef2a1248d16ef5b6b7ae3251de269e4fec94e5e5ed659cb2ff7e3d556ac9a34f391fd2668dec15a3695a958e996ec34b8404e5d145476403e237b3406f120ce57abfd17abc99daf3de2d70c8bdc82e9ee0e4781f3960751f07bf47411e79a1464646d", + "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441156615ed204aa948509f830e7e8756e609e419f8a6f8561fddd9202f8abcba0101cad4adce90c01d548eb5a88e3935668204c5bddb827b618a40626d8bc1281f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000203219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } }, - "source": "crisp_verify_test", "test_exit_code": { "crisp": 0, "folded_export": 0, diff --git a/circuits/benchmarks/results_insecure/integration_summary.json b/circuits/benchmarks/results_insecure/integration_summary.json new file mode 100644 index 000000000..965a14e31 --- /dev/null +++ b/circuits/benchmarks/results_insecure/integration_summary.json @@ -0,0 +1,171 @@ +{ + "integration_test": "test_trbfv_actor", + "multithread": { + "rayon_threads": 13, + "max_simultaneous_rayon_tasks": 1, + "cores_available": 14 + }, + "operation_timings": [ + { + "name": "CalculateDecryptionKey", + "avg_seconds": 0.109839375, + "runs": 3, + "total_seconds": 0.329518125 + }, + { + "name": "CalculateDecryptionShare", + "avg_seconds": 0.613667722, + "runs": 3, + "total_seconds": 1.841003167 + }, + { + "name": "CalculateThresholdDecryption", + "avg_seconds": 0.567017042, + "runs": 1, + "total_seconds": 0.567017042 + }, + { + "name": "GenEsiSss", + "avg_seconds": 0.12360793, + "runs": 3, + "total_seconds": 0.370823791 + }, + { + "name": "GenPkShareAndSkSss", + "avg_seconds": 0.224165903, + "runs": 3, + "total_seconds": 0.672497709 + }, + { + "name": "ZkDecryptedSharesAggregation", + "avg_seconds": 8.543418416, + "runs": 1, + "total_seconds": 8.543418416 + }, + { + "name": "ZkDecryptionAggregation", + "avg_seconds": 49.652658458, + "runs": 1, + "total_seconds": 49.652658458 + }, + { + "name": "ZkDkgAggregation", + "avg_seconds": 20.662634083, + "runs": 1, + "total_seconds": 20.662634083 + }, + { + "name": "ZkDkgShareDecryption", + "avg_seconds": 1.446775729, + "runs": 6, + "total_seconds": 8.680654376 + }, + { + "name": "ZkNodeDkgFold", + "avg_seconds": 78.077101958, + "runs": 3, + "total_seconds": 234.231305875 + }, + { + "name": "ZkPkAggregation", + "avg_seconds": 2.185247625, + "runs": 1, + "total_seconds": 2.185247625 + }, + { + "name": "ZkPkBfv", + "avg_seconds": 0.330690194, + "runs": 3, + "total_seconds": 0.992070583 + }, + { + "name": "ZkPkGeneration", + "avg_seconds": 1.336457333, + "runs": 3, + "total_seconds": 4.009372 + }, + { + "name": "ZkShareComputation", + "avg_seconds": 2.652245451, + "runs": 6, + "total_seconds": 15.91347271 + }, + { + "name": "ZkShareEncryption", + "avg_seconds": 2.472213376, + "runs": 36, + "total_seconds": 88.999681541 + }, + { + "name": "ZkThresholdShareDecryption", + "avg_seconds": 6.197666847, + "runs": 3, + "total_seconds": 18.593000542 + }, + { + "name": "ZkVerifyShareDecryptionProofs", + "avg_seconds": 0.098564625, + "runs": 3, + "total_seconds": 0.295693875 + }, + { + "name": "ZkVerifyShareProofs", + "avg_seconds": 0.216449474, + "runs": 5, + "total_seconds": 1.082247373 + } + ], + "operation_timings_total_seconds": 457.622317291, + "timings_seconds": [ + { + "label": "Starting trbfv actor test", + "seconds": 0e-9 + }, + { + "label": "Setup completed", + "seconds": 2.979362292 + }, + { + "label": "Committee Setup Completed", + "seconds": 20.254983625 + }, + { + "label": "Committee Finalization Complete", + "seconds": 0.006196209 + }, + { + "label": "ThresholdShares -> PublicKeyAggregated", + "seconds": 379.382091875 + }, + { + "label": "E3Request -> PublicKeyAggregated", + "seconds": 381.9183135 + }, + { + "label": "Application CT Gen", + "seconds": 0.3119425 + }, + { + "label": "Running FHE Application", + "seconds": 0.003318833 + }, + { + "label": "Ciphertext published -> PlaintextAggregated", + "seconds": 80.313326166 + }, + { + "label": "Entire Test", + "seconds": 485.793576792 + } + ], + "folded_artifacts": { + "dkg_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000e1f2dc40db945d42200000000000000000000000000000000000000000000000bc38cde1aa22cb5fe000000000000000000000000000000000000000000000001d3d59501c65c5e320000000000000000000000000000000000000000000000000001fdb65cf5613b00000000000000000000000000000000000000000000000fea025eb701a09f610000000000000000000000000000000000000000000000099a31d5419d58c50a0000000000000000000000000000000000000000000000073ab1d4ec48035430000000000000000000000000000000000000000000000000000238cec0a15743000000000000000000000000000000000000000000000001e876fc999cef26f50000000000000000000000000000000000000000000000016ff1d86d471a44cc00000000000000000000000000000000000000000000000be45a89750c5a5cb80000000000000000000000000000000000000000000000000002e6bec9594479000000000000000000000000000000000000000000000003e285c4315d7c37980000000000000000000000000000000000000000000000045c3be92a35649f9f000000000000000000000000000000000000000000000000774ecf2be14f05ab0000000000000000000000000000000000000000000000000002b53e01a9484d028db3b0372cf70506ceb36d180fe176feaef4cacd38465840282d05d98c83a126caceff591ab92e45fa2a8e93cdc4c9da6620778e8e22c5b29c868b75d9b6e310d3c31ecd03d3676db23158116188c3e53d9c5361beef5528604f875d47f6430da4b0162741a4478a6993c322ca93eeae2162c546adf69e792b22ee7d40fe9a29721ad2ee16d01f9b344c9dbcaae3c3ea3c5a09dde1dd269275f9cb213b601b1bccaf864b9cf3cba884ab06b1235ea1ad09d25f9f5ae4a31d453c8a081af6f71625c44567b2fd9faa5491cbe7332c645a24f9c9c948f6fc3ff79f4c8cbeacbd0695e4561a8b7d0b92761edfe763e39983b9749e2cee9517b2f80591981f8361072b10967127b862ab5b83da376af0c1ce237a9a3a17076f970f9b5fbaefabb21e6b66500a97693693d1b5269a3f172d2b565e8fd454e200884091bc9c0822271de3d2014a99fb2925abedc2d016d026b90f03aecc9beb5324f29979ea4a64d4058ed291ce1c39e1d4d9435d8831edea733ddbb559c3a5a97baa1fa02fec3e5c252513658656267eb506430a22753510795a9bec9154b78c5732be8217ec0dc82312dd0f50f7ae7173242a014281649b0ae63ec26096d0ae531885f0759ceb8503751681ebb1062e969d66f1e5e7cafc78baffb7f8b1a455118bb9e1446520fc0525be99999487ddb1253c1c336fccd8450b731aa3ae847112654a56da7f02a2272b733c9b7d31a2e63a37387fb26d8af57a40845e709ba3c4e1c8a898a237a41d0bdec5d3ee7ecc282adbc192dfbd6a55d36de4930f40667fdfdf1c136643b9014bc9340f9748760531e6eaa99075b60bfa8efbcec485bc643cbd1b78463183069bd6487a0fc8172da864dd6a0d3e47fe3be391914d6c81e329bd2a764f47c52f4997c3f2a8430ca679c99a6f0e1ffea2fbd7a0492d0ab6cd393449dae9dbfa2246c5afcfef78a77f0bcc680c1de1a8a29f3fda46eaf9a7ace14165cbc2a076126629fce549bc56da5b7c24d12bb9e3e8dbfb356e24dba1f622793345b0dfb50e525c6f6daa65286edbf55e9f5d56a92e82924936d882a31c9dc0310e5a8ddb08ac158364c37634bf8ebee1cee1e7ba5394f1e10b2b83d0b1b5ca5c34cab202274a01af3f501c8ea02f6986db0d8446b1827d4fcd2022faa954e78e9aec3bb8186a26ad086a6549d1fec85312e028556f7213e4a725a976b266bad87a7c6b4f0f1cf3ce1ccabb1f11f3ff9924857227d0bf3efc6c5f8316b8a12cdd3e7da4481609dd4d212555a700a26914de6cbd75f7dcc6632915094c61ec6ec24eb813170c5a395a67b0d3f35934478aa0989100db0e17e294fd55702df7ad7f3c73931e141a4c58e29829294f9c268d7510c42675036df15feb6b50c7b831d297790aae0f0c3b75bd3e146d8e0ac2a60fe46169f324131fb647cf4d2b750fc4da9e62722de86b0517bfea16566d87b43dcfedd9f650f5d8333b1774d9d6f8b77c015f122bc9d45ac7c05143beffd7ddaa1ac8e69d038ea603ccc156b780b67286b4e96c11c455e5c1df524c5ae657e746ef3e60c8f6b0da74eb476af1e0764199d7ba633054f2cf1eabf585712ddc151023578d2ef9940601597a7681cb0c2b89d1c4b43053df73189ebf5aba935cb94bab2103012c5bc86858cd001d252d72cb08bbba1764ad88e8370c2f76d3c979a20c932ce5edcec2b3f3c371a97c2dac039c6de9164805143e1705d96e0a10f1a419d7a4892e6e870be740ac8aae4cee4e27ce15162d0f514bd517e1cf13d3436600d54ebbbb0fb1727bb2839790d7578e01c924272bb26dab779a11b0b5d805ca706743dcb200bd6dbd1ca2f0a6453ee396afca109816c66dd6e17030a57ba31b9b46b476312eaca02f732cbfa5325295b450691fd3249e466f3311f99a60d01590c1f85ade3d2f0de3ff9d98b88a216377e5a32b6fe740893e4e5fe67a1c93ef089f631e2bed3748ac5d7b9849ec362b7a8e4f11418c50ec3d14891c877c2350771170f90463e9764438b9e73c30a498cc23d403c209f867cb54041c87dddf14e7a0170db0084921caec1c69c442473b83f12214f4fcc66f1aa3d185c8fe2925f3115dcd1bae3e97a757b08882ca10d6ca5b6b149c499952b188fe388719511ce1f127fc7d706685fb33ee80e774d517bdedd01344339ee00a74b2dfc3511f2d93090ac1314cbeb41c89f2cd14617b5965696e0d18b8d4e3c13a0a661313a7af2cb8c4ad7a4c6a0322837187e5f6de5dbaaa74207144c4471a212ff3cdf337d1f749e3cc24e4241b279e73903989dc24a3057c00cc57fcb3f1709bb431c38a4a97873e91b223c6709f18ca88affcbe7f7428c00b5ef61bb8e71042c3fffc919dccd7c09e9ca069ed1d7bb77c4c1acaa54c51f4169f20c2dff03bdcc71572044b5b6a185f0eaea935dbe0203c676bb6c04b83591ca94a869929dfd662fe0c4357881fff436014d3aee362554a5e1d9be1cf54450bdcb6e51c2e1ec340a774ae942f45ae6827afa23bd8b1b8e8a9b732240c66bb1dcc84ab5611af066b0c61832e7db92acef04757679cd81f94ca1d84020b8c0a2dbdb1872ddc0fc91bbd3978810b6820aa2a336a1d97d74d39e82ca9602fa4ea23816c4d133fb820681076e7cdd6d3bc7d0e5e15a6185a1f3dc60326d8cd8a3314a0a1598892960a9b9fea1cba9fd1d2c0e56fcbef30c274232d0d23cbb9a97a0db15d1941f5a64b0dfed341453ffbc79b7fff1c105f3f595418fcd4de049ae1216484d67dd0d53644f49e42be07ba8ce80fc7a3f0b3e8d72f6deaf93d43cae5201f33e07ce99dfc3b88f89cfc55e50be50ecec5fc7d8c24d189057556012d8113a536bb5af66af2c891bb5fe1a3e7830d73ea7f2677f7010ad0c2df1f11cd1c2ed2eabfd9fb7d58cc1c2df2e34b1668ce803f5f9822b6d309bcda7eefe05b482d6019bd64419ac04ad495f3c5219db56982f0ab2f6d8a5327df9430c549f33d1cba8fc85bd28b2b02b23bbedb51664c20d36cfbcb21980541007bd6545d997d1670dd8db62cb6b238af1c3374d98c4e716693d48e51de2d6d6c92dee172c3851f1c7c1bbe04129d02babd13d4420449dc4c70d788e85d29e15a59a780792fa20d1c823aac167c73513400294f418d615ee959a346fba56b59ef109d519688ec13baf06d5c95775d545cee9e830b863df885663184c817027573b31c611c180e1b8d6478ebe1cb9153a24568d713e17148f00e241c5ae94278bc3808c18f96f90699f6e4d7d08014e0bc172ef673c497f8f7c4b899287255b79a0ad7e995051c2aaa0d6c31dc0be7550c9f795ccc0fdf44f2f7c6fdfe3be7b5f3f0d477768b371d1f8f97c97ed109c28c69d38e79ab3203b42cea09d33ced7755ba8d6ef6f877206cfb2b1c967ae1789012cc8ed894d6fae2e7cc2f49c797bc69f40c26f42d7c0f1fd1b8e02dea8d9113c1d96b08bbad5c3b653564840206871aa2bdfccffd6824826e74f385e5df25f73c4adc48ffe8e8d2adbfae9bdb911097a8ba4bf3ed9426c46e6750eb393149291727a7a207844299aecdd9af420413435e676f83bc50120c6542706abf0783d001ac68ebb33b72657035e4abc28f1e2cbf8593cc87c60ccf030125853b79419c3f6aabbf72b7a2014a35dcdcd07446bd08731b7a7110160076de37150cc9af5785ca9007a79cf551f3897eae9a4ced3307f204a975650beaf97b69d70a3c471cf295fe0bdf4da169ecd1c87c5e1df7aa38d0a8a89d2b2c4ff73d6028e7b321787cb5c6845264044ececaa3d6316f08169beba505f03b0f371638b194d13d7bd52fc56bad6242374cc161d5a74bad7148a41dbd49e44104c2336b17615c92e8a9f47f813dcd15e14ac26b160917e4e8b6150a9e452ce9051562ea0695ccfacac02fec03f930736506585b5876c34cc0f3e8a569a4f9a82ae3890e9ce939ae014d8699bb8c52b878556f61d6b28d6c85919a2e323b8ae20887e49e89bec0daf0656c9120e9a96ab1fb8a90cf22093b0208bc132aa8210c04b3b3749b3e18e1043247f34f5345143687085de6be3855fee3f57d3ff513ce23c71d2a3899b298cafb94598c97842c8b1faadf7ed61adfbbaa4577a946392a22c0ff3cb996a5b44eb1fd0b19b45bfce324a3abef53318b7b21f9e8ae564abb3019d2c161132450cd3227d31c78c36a3dbc01d9b97e9dac60c03f21066e9e8a1d4049add692584efb394b7ed23d3338bcf6ce90e4d614337744086930f897380b0296ac58833f4626651e8a5033b4f41b857d25e07f22153e90f6d03044584506abd763a0f54e053cec4b282ccd77b0e4912e4ba6aa6d0b8ba6458cd56024f7074bdd5e6b18532311f08c3dd81d482ee3d5bd269db8b9c8cb4134fc5ef7ac9519276bf0bf3ad7cefb8d1b1e206af5fee249f299bb70989cb50be8c149f18adc0df9bd8457efc268115d4eb01c46f7c7728a94b6406fbf850057222940eaf2fa22fd608966568e80cabf0c7c3274778e47a14c913b529f2ce5e41296942796cd221a94b824646c499d1916ad60e6b2c8cb06e0c6f02c593cb79344ad4c0f183f2bd17d5f4a59548c5d1e6497b2bf9c195248944d1a062159a4804c0828ffe24702e0300a14648c08fc78acb4610d7ea21ca0a8a877960ce2875238ac8f122da404d301c6194fe1bf1cfbb76bd5d84d049a6b6b8380d32cbd3fd6a93b3ab6e31e025ea99e6d366f7eab33e3bd3365bd07df2fdc7accd091ceaa43ca8005942bb92969b0501030587954a6f94719ff4c53cb87cd342424cacfbcd2c284cc652ec315984ac8684998283bd511340f76097e078a74cb26adacb197b2c7df6b8f71a50ff0366b16dcd1a995d3bd680d3dfff9eeaf2901f445b7d39c72cc502c4a17172eae7b16fbc7db17747f5a169cc67969261116b20cec1a21f9bbb5a381d0bc2619803fade69ba794caf697a24ba3a084536d378ae87ec8b7dd87a503028ef6c326a543ff92dad061b8acf90585b29007c3af670dff693d372ee4ee164afa72ab277c2b7c772a0b0c1fc3e0416846a8e3b43a6251d65f38b121a2da40bb773e5825b094e1080bd2732a64f67f01927abc8fb023c796f9aef4bbe76e1a2b1bf7c029882febac380e575de30c0321f451015d2e0109d8a8f9d69ee2b273e0bfc5581211b98ac45dc68f2537f206e9cffcd9bccc8d80e521c20f5ca40992237cd52407e2ce52223e2c089f41fa88b205664e811c1a65502c157a54b98e6642d472220f0e3dd61fb5323acbe5dcb718349daabeb0374c4ab79a93bd62f129d9a7f312140f3db2574888a92b2a7e249b6443e85b8e9529790dc9f95608b357b9aead2b1d855f3bd0f80a1f2bd248cbb85865b79bc61e66179ccb345b580ef58f9a3a760b67a3485360224b3d751c322cb56abf23754313e72110d45bf3639825f9d7bb2b1923960719645aebd84f78359c06ae775dbe1a25554aa421da21690af3cf1a2951448749cbb6d29dab6b92bf2d210ab5f5c32d822ca18f306eb069a8499649026130d680090d629337716429962f4b6eac00d442d246be012fd7e37b9d5f0626466b7ecbb1f0d85eb3864e455f6bfa4997837223103547f357399a630531f313f3240cc6d0e6b8957e8b5d69e3e1afdcb00acdf9bfa44c0d95aa8486cf124b06b845b55663e7b746b967b268fe9aaa9013a40224cddbd437ff0b28e87f18421d3b9cd997000b5c1b3c8b3c07ad4cc51fc491c740f87f0612ec72921266200a2ce15ab03a1689ada9e38bd4af596ac0cfeb07e01f2521943c8a50010801d0fc2dbe6cdbc8f4de88a4d641e5e6a4054bdf369c6f4aac9c9c8634dd42045ac6c9026245f2b6211ebff566030cdbacc8a9151b4365c3f3d91771fc1cab73bdee61033aa539963bd1eca0d7b486ad1aae7dcc1a392e1a6d7db4ea0009402c8f5d7a1964bb1a83eec61f1c7244b3f3d2cd5afbaf399353f50c8e40e0d17a318a8bea1f0c4e79a6eeb53c92891488bc03e497b65831ae91a19005a8b8f8227500091215ed52e70cc1aa437cd82d3fecd2ad70bc347f4a568aa0fe554042bc9d47ebd4118a9be9290598a834ea2ed2daafa454db5dbaf116b5170592ee3bd1b46266770d4ecd15581ed4fceb62ad1b6f31f449db9b5e84e6a6b4026f6624f41345ae480f2e10b0e0e8ed6733445ac0c95c15b47696e18bb98b565d8504c5f5c9bb622f09ea37cdc758effadffb92b67e60b0afcfd43b62d973e14118e33b155ad669ef0bc9051e5600c0d2a84b23adc3ba853b0782295a3fa26c8050330bbc3a572e2202cdea01102f516564eeb5623343160f618982961c575f5311d6dd944159f70b30414ce37af4bb47af31ecd55f5f9f438529fb85aabf086f81773cc11a297eda078cdf01f8e465b7db2f43ca511598138ea42dd29529cb2540e393e108c9c7d22342834557be4349f59ec0eb22e9c41b524dee8f80668d2d99bad886f7ef4a841ae383810c231158a1186cb820e96e9b3e238886c347a0ca9078034370342b112b3121064cec0dd115f748f7bdd7be79c8ac93d19ed14061927bb6fd14ecb2851343e9fad4d8deee07b1b45fbfeab20ec37950b5a684398a8870c61e3adea38d2e5eb4147e5dee9cb6c4a7a89991f7bcd0386b398dca56a3bf8197c7a4a8d22b1441d68fe280ad37e614d45bf5674dc2cde26180d1d064b854724c92532c065a07126b8ff084978b0a878ce40552c2797bcda00b728c74bb3fd8d8637266806216dba4fc94cd3829d05b25cd3f53897b3df62037a6ad6197c3e574bced9421ea1e499047d8270be2a4d17b31a054180724adf1a32b247b5fe8651d75e35edca30e57c6004eb2b5041c38acd34cd374b8e463ba48b97410f0241ca9253ee6ea8d29e0eedc285a0f02b8c7cb1dd62690bdfdd2669d3ea66a205fb5af1209cc542e2d0fd455feacc7d469102bb6204d1007c22fbd2dfdcfc2da5c2eff159fc79c342ca7694709ea4b1a72e320068a09319740dd1c1fe101eb4bfc744405c14cd9ea040cbd0b032af7f4940ea54c7b4e4ffa217928d281e951cd4c918be9778f685e0f8981ec58444cf6046cc7282cba2f6e1ccf0a35204d15e98cd5a5e36e5a20a826cc9ddc82e1971b55a5afbd0b186ecc156eb9c7b53654543dd081f8ce04c8012aeedaeee9220a1532041c28c63dfdf118b3762b4e506ff046335f5af87831be25eb3e9cff93597b7ba31a0035a69882635076ae9e72d56e67fdf6604223cff50a0df54aa08c3e1702fecc7910f27d8dabe86225e9601a0f4977f7b287270f090e41b023ed2383a9cb1e11b9b77da6f0cbe6f6c47a0d19ef311aea2d1843f7d22e374eab5e32cad1499f66162b1f5d386be05cada415a74a9b259a45fad940490843044b1e53eff11e4c7b59a0d817aec0f2068e8e4570d2731c4a2e0b7e1fe50f3c4965d7d9a8e9325d3e57247d56dbb9de92c3042d9996b68c5520f1d6927320464ee7350472a325e188ee96e48ab306add1b0060d4aa16093461160a01bdb265c5bea1bbf59028f3ea0f87b7bb03732ddb3cd405d305153decac49a390bfd0bcc40de0765136f65cc1c007dedf308a8f30fd3e1e01155184026904c9f4ecf03193af1d7f197219b2dcd0a31eb02bc3a498c913157be05eb238d6241422e692135300ed974835179d8c114af12be32df6795dff0e160bde9a5855d3887c3310c5d2ca5a5b80ecc1db01e70685b2e33614ad38c65597487130860c3e1f918cc1fdd59ddffeb5882b17341c3d6e5010943857fcf27eb9177d1d01f4eac89643c29832809590a087942ce309b72ec9743d9b2ead95830632999d0b23d5076b9c414827ae29092fdcd1a3334443e7eb4946f916c01f935ed2ad90c9791f24f212c220150245261692c3c674a1e9f06a8f19c0cd8fe8468834281f613085ec99b381a74bffb6ca2cd8c7b1e70411110713313f1d001cd78f878aef0f570dfd1ce8c165d3f2088c1a742e0018cc83b6b37cf9c2eb9af4563c051cae7fb9f5d9aedb516c2defd636395808025ef29c2d3e0de265b8c6faec88cbe1e1d322c7cf4d2f901f793d46762bd2a233e91ce0e7f775e765c68e8d5d3f840dda369c945c01c0d1e9ec1f4c9a2830b319aceb05b2739018df45e41a08164e69bbb37c1e9b22d6e0511941f889afdcb02d986c02f9ed82d8ccb94b3cc9bee7f5079508d65432d151cc7b4c40e3ac3928bc5e1d53703b56d9caaaedbb983ef5858050ed237347c3a0536805c06ae838aee568ab7882a5c373d8634803f950d9ccf481a4ba060d3ce2347b90cccde3b767bcaa8e3b06b314cb39c69c3504c95bfd16300275e1b5b3027f896349ff4b251814b462171fa7792d203235cc1ee5719320995c3d88068dd0b8eebed21533b032f57426ba12a65db9e2326594c76ed3470d0973f432669e4251edc549d8eefa2db3a94b79e868177ed4876e24adc09b41aeed80635bc0d101b75a12e64fb119c6514ecdef26961f07e210e1a72ccc86c8e5fd3e22f15127a28dda0078ec59ef3aad33bf8c5799c0de2b6c8873d6ff719ddc1c74ac99580052ae0832b566b6ea165a1d27c369d5a555ae8788011b36c8595e287545e9ede4201ed52c1f7dd087bc79b0f35b267b3fe5215167e0dcad1bb8fcbec9ac4726ff2023f9f12592a9817372d647d280e71e90a7d7c39f880e5bf8896c990bc8c4c291828d200153ef1ab2e400d5bf3ba3f60efd724ef6ea66c2c75390eafb1b77591017a187aa7128e77e15b9839c9115685130eb47eabb280212f9e8389b4e5d8061a6295ae85ee72c05994836f800abc11b1175e7e3ca65179920b4446192bbb170518689a2eeac670ee167d446b3819f29b16dcdf5503b0b42fb8dd28d3b3883f13a4bf36b2c9504518e63ac1cfad70396ff85e3b67fbff887578d81828fe5f111d7b85893435975b5674863b8a3f9a76d1cddc184eeee39db7853ac420f095170fde115a7b1b3a7f383ef87113a6f77a1138edec7feee548490499697cf599ef2335e6f9b7fa4938679371ed07813e058b91201a4848222fcc5e3fa2d797501a25a866fe0fdf394232c5a494beb9e63297d00195efb37074430e9a4981204cc61eef085265e8b8de1d6cd870769008211e165006e8b3ee5423bdc44e5198ff531c011a4d3bd57fa161a92ccfbe0d5597a2aafcaeaf6cc042b5cb79d47e4590012802357c661e7a87a56844ce37eac8a5871cb85e2f34cbca0acfa14f77566b9b0fd9a48d11b07e199d9d244cfecec430ced755a4ac507affbe74b4ef2ef252861219813dc856b9280a97a478755925040ac19e359f1512232e2a1a348dc4ab5b21d0953cee4b7841b5e6fdb787ba135d101ebac20752ccdb0bee7b8b8b59f4492cd7062b7535d5139c66c6380a230ebf3f61b18aa92d61ace15b82be68c445fa2b3a94148c49eba2a8d2438db2b33b0eb48f0f7831b3632297f29fc8413d0fd904a20d7ba25398186d33a0eeac9278c4d31547d3a8872e3bbfeead80350f62b30116d16f6518251aa9aae6ebad711e28f87cc9d3d0bc79e5abba9a95ed1281382933b1755c135eb4115630d3e4dd4e0b7ca034e98479edd3c50d57433b7bb0be00dd1de6d8e5f68454376add37ef224ca0aa7cfb5ed03018f297fd999eee543d21cece1629756ea5e93104701762cdc0a55b99cc72c54a23127914960a654dfa1fe4ee6692b34adb983da58f330e7e0c86ec396c3116a6e9caf0aa6b9d47737d05b91d24208aebcf80cfa68b31a98a009e61a68452ee12b07498ca5b18caaa5515f506896619cf48551316a095ae30a84e48abc0bedc74d6825aa238ceace417152211741dc14b488c6f11b0298d1e8abe2f27c2e135c927146ecdf7ac56ad420e36ec47a8279d5cabf88a0a360d43bfdfa43b9e891f5120955f2d4bdc121606227b6c15f345f9a55b233198162bda3808f27eff2ccbd4ec10a29d713465fc980792f71dfac2c03bdeb9988d1584fa91df81eecf435dac93f6ed2deb4cd9179f076f65880a7e2583a6246134e87b59fa14fb6d082f1b06b890b3ab334c87663126736ddcbe0ed487e975a29e2a5b4e80cf24a821f4853513b383113ea252e5341676f53cc7376901f1aaf24817b2c48267358897fbdc836fd4b02fe9e1161daf0850436efa21849fe994db36ff91a3ce2a677eed3ee2117094ed02bf47e3c88406cb6ddd4a4c69df5a5667fa9c2bdc3a6181ccedabd0420debdd15f1b163f15724845bab70224e26375714010772b3c3000ae68098c125ca95dd22805762a1d501748ba4623c878c2536d2eeca896267212a605808ce75b93526220c2c18c2fd0425ecfc409eda6e0dacc8de3eb8024d9a20b29a6fa6b729f72ead4a9f24c08812311ab4d54cb22663a5a82441ca9b84c95af6e6f0f00bce270fda7e439b4f3d15b556c175f8fdf289fe72668fffc1804643e599cab4caf6bbe7d660a2a1324f1ba66f87bfd12d5806cf9bbd3034648f277cac80e3dad0d4d5d065f6e5fc4945068922e07ca60e5b244625238eeed4719bbdcd8d868d756bc12a956e0efbeec00c1ab342d27f1d270498b2103ecae4de962435aaf88ac04186f4c8a3e2e71c2c09fa18c56627bc235b09d1fc39e214a784927feaf510c3c0414168f4cac9d6301e80d0b79b97fc8d550bbdc44ebf5846fcc340e67383c9d53b2a1b94586154a7267c1907bfe9ee68573ce8d99a711c9da911d795fbf0f087e362c461a4074a3a1cec33703aea1b12f87aad29cd97b8c0ee78cf8d09b2a1fc1352c497ce72aeea185431e962667e6a48126e294a1fa8028a0a135bd57068ebafcfbd589cfe535507faf50b320619186800fb993ea325d3d004d6b68be39fce6d70ab560a8efdab21c6195aa6cedf4ee61634f96862b7f7992e9df0fa250e0f25b671288bed15151d773286b3543c0047007a615096bf54ccb45c7da10eb3291c28ab2cfdf79e6027b2a9261c095c78470edb892fa58979c9880797acb8f09fd99a8cd441cc119d12d7cfd06d96edaada9aaa5f4af9e3bb5421b83f6664683c38fd04800d6152c317a0e3ed68287a4e6c0389ad3ee54434e948af4fb796b6d213911296cdab398c1e5ef689841cb2e4aa63679052def2edd541a376109970b874031e99609fa8f000a06778dbebf666f4e6f8e41ab20543083d5f506b7f88ef308bdee04766011f0cd392c11bc5fdf32fc7a14fa91c13bf3aa3b9be84d50f12d6203ba8408c630a1e06c80b74ed54aca8519851dfe341de87ff0ec0ce0b72dbcdcd19a5b84bcc9b041b2e04ec955f754ea52431acfdf375bdd7140f4ca9a0619458e0d197b9d572184832627fcff4170c1d05895ca491a09144c5209c6b0137a03579fe74b02b670f2b282ea5c15aac900a53cb60309f1540d09b393da213a2c6f949992404a50017cc3f11c854a7d4b9598e3bb233355c0f2a782c32b5f1b2954c206d44cec24e2fea355dc6b919550164a6814945664f397813afc2ee4939962ccf83edf950890f245df5fc5a4a027a2dc4e60031b93717114f900931fc88c43c6db6872ebfec1cac247b216f38de3af3895fcdef00eb6d9f00c32de74bc661e0b5b123448ef61a0b026dc0946b3abf48ef6ad7c763aae1e0162a13fc605b324ed9489b5957e806472b9adf3eeb35b76e109ef09902b907f8d314bb8ae5b00f35b7b3bd99320c163f1d0f7a9f1efa43b36d29045ebf4d1308cddc170acdf6257d668f89665ca10ca55653f44c2613af78e20132c2f8e2c7457560d670804077fc3b8b0ef8cad8188c0c24e2aac1b9824295e7f6578738378c55d654194282d186e7ad295bbc5d1f55473be32fe31a919fa6729dbd35c77aa45b1d79fe65a94b67bab20d47bab129de75ca256848e7f6a6cd9747d606027a2c15c7c82996cbaa34275bd40b9b9d244be024ba6672e1e7dd1dba510352a9445825ae47bdbaf81596048dc3a7325d22119dc8ff3f458e8c1b0a8048847417c41a7f6f4666a21286b4df234229225a180ae1467cc29b5bf788164e5c60dc9144bb4d7a03d9f077e15476698c7292eb25c42282e9fe3a164095d306c4d50583d0836c151d2e2ac76d704124b589e86128ac118f9fc484d30f6831d630663236b3ee425f34363d4138276c6b77e672cb2316d2abfe95a181ceee595ed6097f593d17f5f51fbff779e243b60cf18d08fa2588b099fe34c9916fa0dd0d1118f4512e362a92ed4459b40ac521c66987e8520d3e773435c7211b74168b52794532a63a88e72aa6b0f0d4c426edda82088bd80d61e06c87ee0577c1633d6a061e1dd3cda18ac626bf7912d994a48ccf30d1be25d3ddf685ba8df7ab532aade5a0b89f4188b835fe8627416d99c13fbd7312752061e846f342a0e53aff64ea450f72494e953f74c31ca50599a9d32e52ff6fba1bddbb5989abc7e68af1bae43168875468b0432799fe1adac2b610728d61ca900456a5cf5646bf8438251b7017636f3bea7f8627ef919775ed74205f1e93f11e1d347ee26dd72e31e5f24f8cca5f2cd905ea1bfcaade0ef1b23d0555e2b128e92c570745225a2f80506157bf8ddcf0febe3b2d3b87284803dd3762970f500a85062d89b8d679171c92258012498996642d9f32fc9b8914223ddf76b9228c6c852c41f9c81f6e1b8aed64a680437d2e8fc812468bd490c07d7d23ed50c0de821816380697a0f0c4600414df4a2cbed15eb6beccae630e87326898b8438ac274330a7009ed8ff4eeba6d0ec8c7f10a6c5958603769c2d49c3f451bcd83bec98172182bd68e46f70c6c146b3df9792afcf807b065d1df44b1d3f9a16cc3ed7c56300332a404de00cc561e8abdb366b02bb97d89e1783b88720eae99e715f6efb0dd1f16870ba292b53acca4709233394d4e830017a4925897bf1a7f3c2228723b6b0aa4784cdba6fab4402c28aeacad2b1ad7ea07fe04dbf84ec0350d4c0a38a5f22dd89059b1d89dc4854fbb17bb68850ec92224f2df873c113aab633d6229df860d9dcb5759cce6458d0d0d068d65f11061e7a66c552347b1c0475d3adf0a117a15c349f90ba7e0ec0ddd861864e843243d00205d6f7f784e63cefddf6d2b5dda21e60167e934049f40c3c334327300ae1fee1db8dcf91e861a288d5b8391d68d25ff8fceabc18168a51d1bcf6162cdd075f980301931a732067db196ede699e31593c56a31ca830f78c08d85f7d0598cf18df04d1a83744be91d62a9d48938360dddca24726e1709b34fa3089cce740aedc2468af8bcaee7e8e08d4a1fe2ff7912bbb10342e4f1e0449a95ef72f96f0e2cc86646b40d0b551593f3f3990a56812270d6bccb9c5122672ed5f45f1116756edc25b1053a29d63b0cf75220e817e50b1b594eb5ecdc079a8efb169fcc39bb820652a7921b1bb5cc9c4822a4a06aeb22c90eccf3c5d3db80fbb6d3e655e309c4f49e6c56edcc158feb0ecc59371f7d1fadd6dc96f1bd1bbea4fb37da9209fd80d90460baf6539345ce2f3c6c1f5c812074a5f478b326415d3f00d85e648be949a7ed61821b81aef07035a8e614d30c0a95c778b392a6c9117bd600c921f2b6b584595ee597384de21cadac502041981537a1874c7e2892e52bb994e8c3f4e7daabae54a530de5402587dd95a740df90c5ffceff04a2316ec2e79178ab83c9e36da6009e8822e048a0cb4e3ecf78a3d235ef3d535547f3823e356568660deff8e6b42ac6d603904f28afb5d089863b405e9f4140639e2371bf0b03d30c41928a0f4d2899efb2079fa7276473d48b26611221288b65b272f62a9594276fdbdfb7c3a75f4280b93afc08c79bea215702d1dbc1bdc87111e706f693fb3d720a0f002731f7fbe7336393b8816aeaddcd9781febf673d810faf0ec607e25e578ce30710747cecec39c45317a4cdd837e436610bdaca35664fe436bc093db244077fe02b795efd71e140ecc03667852eb3af62f1228a2ceb412f361e3d17623d587eae378b63b5f67a2d6dd0f63ff41fb3a0922e3f22c547f8e936f3ba7a067d15d43f8ffbb69a613c78ba56f51d9345c54fb15228ef14f959b31bfe59542d1d96787d1b10692ee09c48208ccaaa8ccb67df32d091bcc75cfb8f30ed28bee0d15c0f952c97354709ae4ab77dd9fa2ebb897df2ee1541b7328936f0644a69dec6593585b86c3702abf0cb12d740361b0d7d7232b730943361923d9c3f47bd914be5e4d06202656a3521b75c1bc358394e95d4b283da8b0a31a6a8acf838969ddb6a54dfbc585bc8871a31cea3c2d0772c74984283dae9918293e52ac715eb27d8ac775a79fbd4b0b0f81a3c66c44b92c05c3812cc12592cdbcf2fcd8ba7621200be3113f36ed110e93683de0c4c0b88c66efa61bef685fb8c17c46ff000c53232380be681a24affa72d07ef36e0ae5c0dd3ea616ec94567324fabe7332389502a67299e45c203908eda045ee73b927eef6129e17edceb74440d44896e348602d32c40312a7cc8fea01c0bb61bc870ea40263ea125d48adbd62e87b1d254ea192e3281a08567aaf8219350686824d19e74796742a05c1b82a755458b9345fc7ff8fd009630e1d46267874bf79a88eaedbdaa5e61e435868e8aac3e2b4370a8f54ea37a111c325f4a07dc39ac01746a3f98e194f0cf38a4652916baab0771f2127e9ec7791b0e37b765985c5f0d073e42154851f1719789e2f4de1bf9b8c3d81849148b1df87eeedc3d6583cd994c43071e6eb1c0150e3ca9f5b8a5f962ea613077421a8f906d4aaa5dcc35c78ef6d8ce46ad33f", + "public_inputs_hex": "0x2138b0022ab9af3c96b082bbf307bc9e79f8f1401462e3ac1cb3a9913a5b856c18c40bec999a837ec1f06dcee05102acdef50c501e771cef739dfd0a4cac5e9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000211521e0a601b59f0fa9d199e9f861874db5d701a0c38f6d725d9fd8c1f0b53da03219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218625eaefc46d4dc1d14d29441b83268d90e246af546b51272b038fd206edb2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7296995105557a58df75d3a42759d29e124a15ef43bad6b7fd6a9d93d4efda1c900382d23bccbad9ba827179293d23b719de8374589fcad5bc6d2148bc787593a" + }, + "decryption_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000294fc7a9da860e0de000000000000000000000000000000000000000000000009cdced94988b65ecf000000000000000000000000000000000000000000000004d00a28a82c32ce5d0000000000000000000000000000000000000000000000000001fad828e01b9700000000000000000000000000000000000000000000000c0ac27ebaf1221bc80000000000000000000000000000000000000000000000033e0eafab14cbec0d00000000000000000000000000000000000000000000000757cdd9da30a89f350000000000000000000000000000000000000000000000000000205d55489f97000000000000000000000000000000000000000000000007def0d56effcfcc6c000000000000000000000000000000000000000000000000d838d03424697d260000000000000000000000000000000000000000000000055b7cae97a5e905a70000000000000000000000000000000000000000000000000002d8175302221e000000000000000000000000000000000000000000000002d7bc900bcb74da7f00000000000000000000000000000000000000000000000b8c40c16d00c8a23a0000000000000000000000000000000000000000000000013e601e60b676ff950000000000000000000000000000000000000000000000000000d0468cc026ee2459e202e853593058b1db0784b0ed9b36eaf47ee9cadaa08014bf4d8cd3185a2f2fe48532a9a418b29e10b078d3695ba07dd25f5e725ab90220be9ec08687951f316bc8c628606f4298833fd7f9d2c87ea17d01b5fec6bc88ff5919e022391427f7da7bfb75bd26d4480f07dd2369b222049599bf23e227c74018706718915e1e3c8e290aea2380d2f1f59432320fda6a7528328dc891506ea8c73c0877633a237ae8e7ecd4af3e7214f4148072a8b265521d50206cc2e044ea74aae7a67d1d2ddf31fa3c5c4df22481e54e28ede606388e074f21dfdfebe4236a36d36636f3158452502158f58655a3c809c0ae7ae640f43eefc892187fecee43c03179178f04ad773d57f57b4a1b19b4b5c362f5bbd0756fe0fb35313d65e4a6f3c2bbe6842ae28f45b8db241520425f0ec601491d05902e4ce8bdea9afad1f6e468bb39eb2cda34d97fce91c8aca86243f88b865375f479831ca9bb80e8a763469dedbdf92ebbe029e22053d8a32a6d42d9f14cf1d52b663c7fb344f9310eab3d996d6878174a1ff66145793f5a9a9ebd7a951717898cad749fcc7a3006bde824edea17682b37e47270a2bed20f65231a78178a844ef051047364e82a31adad5516137234247998035db34978941f97a592a64654e078b5acfeaf9f5e320d0f18e51c25531c32c6c557ad2f11ffbddd2ea82e89f58d036bae5c5e63e56bfcc1effa99e9d81056314e8ebaa1a4aad6f150638427e469d50ec5435e444f96e5a4f69f34ae42217aeb8185218b67e17ce9681eb4e3a675b2f2f5b4f0f15c7b906561ed7fa55810f2a840ef501bfbadca630161525a3f54b774d877dc386d9fdbc10e2c95a83d18a0cf0c5731d507ec4e5f0f867126444e5c9510794038b3d3d8831f09d55af50394621bc1804b8b4583f3639687613e55138bdb626de365f69aede7048165fe23ca346dda0c5133017abf93d261f82c83099c2c33a8815fe4f092e2ef49fbf5251702d2b6ba4cc3b0f675e38bffc71ba88cc9838a207f844154272c69b01f502d672bcae5907e22252e8262ba05b4f5b7b1f706690f28650fd56e8572d8c7220d132fade6944cf98739494d36ac2e372e7f1d5a4a4e7b8256907b9472fa788b153d4f292fc4ad888ac658e37ad6e85dbd13125f36ba6cfbcfa9dbcf8e4361a5025de0a5ad4ab5c598f2697c534de6914c1ab8f9751d5d7b2ae666e5a65576c5224a88599738d6ed38469061203d645ff172ddde1638f08da2a3bf320edacfcd22b780255c9857273284701d0403376ff3260c92eb9e7273020f6473712248bf1c43a07dab1d32fcea48bb38a41f1656b5ec6a2c6f9670de2f1b60d32e9d7b7227c52778ce41c42652ab58a56904946766edd2eb19417653ebbf939af4dcfbb7163359c46e9022063746940d4d7fd8fb0a62f0826f29898f68cb38d7a0177a5e21cbfc8e122a0af6557c749be7e61939da64b69c7e18000df1cb10977b08a1fa1328ec0746fe2e2142da4e6f9f279e3962a4d80151da3b2c963d7007fa7830230e24dd7805f5ee35897f14f267cfef072a2a7d4d232141c32f7688e2bc12ac982eb506295afabc4d912d6fdcd7c96293c432c3d544bab31a760021260d3edd501b2aad6f77daecb13cbede2301d0fbdd0d3b3bc5c50999fe8fc82af9423c4d9c1a825c8cf5b9b204f4e3d1f2a831fb7cdd33a69cd3afb68ab16a16c3a6c9643f1a408c9e6f64e50245cde76c4aafd47db8ac2f5bfa0cc8f4bd69e082b66e5d380800d387ba9c41fc32f3bcfebc1ffdef85c488e25104c3c8112540af09d0112c2e6c8aa2dd27874d7774b1ea21dd1b54f3c1f9fdced53535104aa0bfbbe49c310a9880d9e7cdc46d6b7bf4609ed6aea3434e450a3fb8be09a879e60e587479dc053dcc5798759ab8f96da932d1eb7cbfa4adf192f00dd167aee524e3329fdc4213d648dc03c02d6a9151ea566a0cda04b59b92b21f0053b15511b6378fec2feb119eea1ad6aec36c068dd52f773c1656b9794c65a7f723a3938dd4977c1c0d3603e745aab6b902d46834b2820f071764b6574fcb80db1c9f13b73cfb6e4b292b2ba0b64a160151353d27c938e2b4b18c5c9ee97e23a3c9a876fe744bcee41fc225a91e7ebf32670753e3ded6e2e9af3425ad3e35e87975ca2c63b2f6186d199b19cee0b57652f3801788cb5f9ad4778acebe7b9fdeda43db9c043ef4137a5b011e592540eef6d70d70e20021d5eec3ba03672e8dede78072d065ececfa35a733198aaac4cd5d63428f39a8e5e21bbf16c50e7e6557c8aec4e0da20a36bf60720056de3908e28cf7581d48db03874f6f6916afe7d0cd3309d4a52328ee74613ca0abbd999c965bc5919e393e49b00467275c648d3ae08d8a95ae793364703219e0bdcc6722159598711d8523ed03e9297bbb79aa6547dba65eb4c35da53adadfb246b58d195676d5b197da5345ecd3c9d523933fa372d1bdfc7b0e3f32d9b00b005f722e8459660830d6526efff66167c6912c7cc6cdbf9efbe76be95246b5a571d8f4c85b490b83f320d3b1dee211a8df62129ece02a51e15a85ca6fb9cf575f24b4cd1b404495341040be48b09a293de2a47fb3b96fae5e6404d0fa80ab4752007b1ee2455f3cfe81f8a0196925fa9fce41611fd8db8d24b0727560d9418eef2209e0ca5f5e3c8cec70623831428d3c400767faeb6afd01dd445b040970f61f17a7d3b7d45bc6005b2ba45d69902cb0052c481b8e77714cafbf97de9b1d69a80f0424d92f06c10e3250af1362c162487b277a6684439aa4ad6cdf6a3bf22761231b27fefbfde64c56f987d91ac5cae036699a100e5361f01cbedde2d18c919e24c22e8de03bab49e04dcedc84a3eca8530c23f22f344ad3f97840b9b18a61e42e1adbb61e311527f8cd6011466cae22387754a8347c340c4cf1cd4d3daa44630cc342d855ba56fd02dd12ebd4beac7623f4d8423eb3abaddf087abfc4287ac01018611b6d426257d5658cf92248dd0519b0097f1ffdf13d114e1a6402b4ecf91f4a331ca61974ddc19623097bc0fbe6f8c015d41874fdd46c4709779832b9a21659c619dd72d147107def203ece56450a8cb78076083d47dc6d5581c0e4261720106c2d002246ad9edbf060db3a529aa65d95e41286165f54e341de6619286f11071ac18276fe5e98e6097b42d4a45bcbe496f88bb6172c031f6432f07bdaf8291b40a45182a9ac24da29515f13705d518802bbc5885395dd9233d953e9bb9d290d91ef07cec9a3de38045ad99a1b7828791ff35660ce77a8848dd1180b472b00856c9b76a8e7fdc5653efaad0154b023f8d930877c53860e3afdb8985a8d2825c2656baf2fc91e8a295b7fe091742c01a3c9fdf5593e74bca97434ec6cd1531edf169b86a01057d936d55f95b3571701aea73150654ce6cae2f98fe198f9832cf05c7c4b579f63985db2581fc7af7ada21d1a6ecc2534ee77b71a9453f7acc017982bac86cab3a4520948f894551800e6745ac5397bd3af021c2ca9e9e7d4501491d40f0262528ce14e591506761ec1f1b04a4b8218dc7240de57c9424124908ff18ea7907906defc1dd158413cdb5e6caeef68b945cefb0c594e236747a1b1dec6fb2c44d7c5ce2a82dd61dde2f33b5a68855602173bc1fb3db2f2a81ed91298d4736329e140e147493320209d367b33e0a638c7827aa2aad48ed8273c3bc0519bd5e4e1a9f986e905ec2a1caa2903929fd4ed46bc7969757a46360005c122e0acde7ee62766d37ae8a5f2e4b547e89dfaa316652ee28ebee61ed6e956fdf052a556d5531ce1e88c4b764707f385139275e389f61e5f89b98c662e5ce990c10b491a61a4e90b0fa60a4441b855471136454e47ecd23d896c6bdd5f09e718703bb8022f7d8647ed9c8156e253458c01648f194c62af28fa76002d10ee418d403203985ec4066a71034667f395f24150e2ad69ccd6231fa3130eafa0670651e0cfcbcec847b040514e9e552d05b09dcc1eadd6193374d776b475d446b1cb961024cd1f3ee9bbf2fc7ade6a6923c1f3f77ee63afa7b1dbf88e0f26f72973cf411f0912f87f18d688280040c40934cfac69db7b0bc9e2dadfbceeceb5d68101e62c279edf9488d4e212ff015caf57d42687fac2e10906637225f287cd50f755d628b5c33d276e3a54de8d8a0a187cf0d41c3ecdbdff4db32162535b35eaa14e592e022ff231c63501d7f23f49b905a607abe8fafa9652522145449f412981d4d60a9055cab29ead09f89003ac2c1c78ed5ed99adc0012318dcfe8d735884ad5df0874c62cc3404cd9e8b614d30b0145e71c58b665c0d2fdcd725c862a6e39ebae0b08331739e0c419afb6f8bd91eaa526cea65f02ee0d5e5a6356c7f43f3ebf932f159efd7d59300dee06c8bbbc756d846f609ca0770eb0402564c490a9d350ba11bd5e5b2e464e2f8d5e7943c93e84784e750178f3ad7fe184aac2bde41f03d2021b45a3bec599ad5cae13e571aac7d3bcc64bb1270f8115e6dffa26c202ab6527535fbd96e3ee327f312ed59b386467002e4b4f45c4b2ac2047e7962b3c8be217298a2626541552599b72662f0569a7dd07facb14d6d5549ac8c731ed8082972ce63108b948327d33e991f9ba410608e8554f2a7490a6bdf46af259bdd695082df8718872508971841634faeb9895de0d4491f3e2017206c97f319a8c0a6e4d1c85cad433989c91a01bae57ccf6ec8940a99850e661caadae51988730fc385229bcad6ce7b97a0eadbd48406b5fbd2997e41ddc2a79ee8224037a36b7cce175218c1c06fb11cd4d271d994ea75a6c4b317b1ae0992df5f55183de4697818f6b13f27ed893be4494f3e90291d27f19f89d80eadcf8dea2145bcbab08b546c8ba194c6cf80a97d4cefdbe79aa1215d6657894192b0216324d652e1d21e124a64821d4ab31faea2074e75791fc017f84acd450c86dff047264915bcc896c3c543c2edd149ade794ade1f7994d6316eddc373e183d6067d51b72d228ebd6887162b04758b45e2b15631a42421c06cf2775240ffcc351f9daf0b357be8bf7afabc2b1e93f729161a1e166ecf00b2623ce8fb94ef53bc8a96877f34d828e4f033e4362f1e27ee8d03cefef5ab49c44a121687d7c7d245efde0b97cf73bddbbedba45f2ff6bbfc4172d84240c261bc2be4f749bdc75e17e46ccd3675bcbc201c97533b111cf3aaa5e460acb2817cc870eda8cb16ebdf7dc00cce816b3574c4818b78bb1d2cee7efa2f46f9e845492d83a5c02e885f2436ab71ca2a2a224701f583fe6026d2db3b84d0ec601ac908afaff0c85c23c705dd823380cdf0e081247d59b1b60c88fd5a27d6db83584f5b89a34bb35d4c35b96106ef73d15ae819fcb47ec96717e5eaae59cf0c11214006361a744d6ac7a25ab5e77f2f8ffc2fb929f60ca0521d3d5555e8794c7977e5f2c3f82566a0dc3b02fc334a5ece8b07c4dd72baf91f227a153e8a11407b673b099ed5a336d10e1ed0d078377159bba4d50ebd0bcc7516c2eeb310e1cd867bb3e48a009ba73d9e0bfcf4e3f09640cde60b0e5923e6f7096155a3ad2a98eb2b181b6ebdafbd076ced5dc7a3480b10465baea717e6b61f293e914219dce1f1b876a424818aef3c0e7058dae0c5a2d09915e076c2142f1e08cd631d377737ff19299dcf4e7ade54fda78a166267ce8c1094a64d390b8dae2259b6e601cc9d235d2914db51489547d9ca30a8c2a1ee2e731f1028564d14f4056be7c0fe8eb2ffe62a2fb7a5ff145d688ca30a27f5dfa85db0c3aa9a860aba12a1b7d5cfb9689148028b605a95abf982a4c8d4bddfe3af32e5d6f7b26998be18aea5924288152469f17a16a11660b072c5440053e6ff8a5959017dae30c85e13523b6fbc00afdaaf2ff8c1a16583c64e6e1bc4959fa154d322c947d0955aac28a3b1ab3eedec9ee7ed7ce944f7e2f62e2c48c22d5592dcd5ab0222ac56441727ec263df9bbfcf0c98055df596019ec2ea30eee2b704346cd7897b10938666b1c4d23a603ad3668d3a0d7fd8639adcc00c86d35f636323314dc4c2768f64ed126b0a6cee630f96df5285d06b336f819433f242f2cdfed6288a139b06f7cdcbd11d13dfe7fb8178badd5c625b0601f1fc05b82d465ae998675a21a119a67fee024db3198472a84885b5625d99d048f795646ebf141972dfc2ae6b0564fe8ccb7069d921ee3be84673cab69e2b5377767408be6057236e471a0987befc554b25617b1059a8bb91e37c219f3cb58dddc5b5fe6034c30001e70f8348674a57a06372b865e3326ff804d8d31f229710352350b0b723d51d760febfb162c675cf34ab201ee76607ebe71a1b46136f68d568cabb46ea5ebf5affbf919c375d38c697b20b248f0fe7206cddb60b9365cc053a13e2d6586790947ea60bdcdbe4cdbe65fb03053f1ad5ca162d49cf0ff176a41101c959a27cb3202c913a668fb3db3091f40684cc1972ea56baa750ade20ac6489f1d82ccf49ae3f850fc26a91986a46f071c3850f7e561f7e99c197065bf71d303f25383c380ddf55266585210b53d36fa149a217ad688dcf0e8ecccf2fe65ea3fbce0250a65b277ce4ce3cac3cef0b38c1c28e6dfb6715f3c28f38040083be9c37beee26aca1200ae15a34d9490dcc5412c7fb4c25ca64f2c6d07ea3b7a4761af12d0f5e472e2081baef1f882111de6831bbb4805bcb6856144c55d7f239d1438d8e0866135a6ecf5d6ff5bdb392ef4261a24ed4a439cc079330b5cc78e34a0efb3ca6a8ff36756b253befa57238876a02bae552b5d9384dcfa2d2154d8d34fb5e0c3b87220792b9c408ed648dcbbd4aa04ea3a463d76a49e365d7367f6f04956ff2702bad4f9cac463d01b43dcb044cb2631d73967b28f9c9da4444f03556276fef611323387027818cebb63b791b61f0e98d4aa94a4118674aa11a5219f1710a2dc474975ebd3dc436b77ca2c9466411c03502ad4ce5a43e3e84b403e745be5b3fb4e8d3e833dadf73889b1a850e031115577c21a2a947e88e663b32fc89dd3dee7fc04270ec0e98dd7ba416b3109de1981d92f1918ad98deb2a72a1fb76c053b187103874333f579d5949f4d20f1fc0cd9938f737539b95565068f672871631909351fdbbc8e6e3880a07a259fe9111b2510551a619ac11bcd3a7f9c8bcbf57da7d3a39c3c03183b4386c8578ee0711be31df13d599e5f1d1dd6c3279ecdd464ef86e94b15a30eb21f47a60fd3ea9b2fc64ab168b00d7d3a5aa6d35889a614b9913222bb89bb344c6e8fde590b413e2eb668737bd00ad942e02af0ac0f1f8faf0bb6a08cc08ba9c78b2c293e4cc0d62ba094060637baedf137e4d78103aa629ab3328a3b8adcc1b62fd06027c06d68186fd2e04fe594bc699eb568edc8bb90ee3aece987e5b2a2018089b5ab1ca2d619ddbf05569ceb9d23e1f1fbf61690d3d2c9dba88e27d438d84e4bb17cbbe3cd1c10d73d1e563c8bae721678c7b22d9bded93aa4527f2135678dc198d0005c5921a7b48aecfcbd1dc92729f0360c33cc9ad7b581cdceb7b38bb8b9d822bbb04402ec2a6d3a66616c4ff68d09bdcb6c4334089dfdc6d3a63155be13d61023c28c1ca88a25be0977971236b26635533eec64b627ce11518adc43985d69308910220c85bdef91505bba10f99919a6b5a14b66a6a065ec49dc998e15b064ad61c7d527411267826844692b4f19b8f6d7ed2196a25793a9aa1d513ff58e78d98c1343018697653c8c57a4798baa88cf2e7dbb3c8ac5f625fe8b215c8c772b99ed92d11258580d1282842e8b0f4035c42b4aa5f87fe6f03b79ece85188db4167b7fc2c20446bf66291fb855a1d9a39de217892b292f16144567957c879fae867d1e96215f75c2df160eb373272da4d441ace877bcd99e2ba9e917e4eb21da3306461710932e3280d8baa624131c6d7207629aac1dfb7751305c97ebddba4cf32f505e92d1f7f3417d2a7c7e0f2f45d2202ed3678bc7b950c2046d044980fcd96c1988d10841c8df616fa31ff7162f82167410d2e8295324d39e42e3558654898c73a082003305c12c89396909e6197117db6fbdd22ed67683083da843b1ee5c9ab184d2a1d70e72b415010e22b22000e198ffa8fda3d1915b88ea4be61fa078d9935d2162725a2b75375cfc381a35ae2c6cd7f7f37a232ca024c412d62410373d8f3d41f1c246f3f9b262faadbb872c0eb846d8ccf186a4972e040f3c67cd894e8563b253c08448b39eb88cf2795df514fc9fc043a9af9b3fd443b155d1c4cc4a02c1516987105a98fd4030fc588ddb086f85d0ef6192fe60e5ae96c8fd6f689a734651db0ff009896d584482f6fd532192bd37a367f2ea8f14f8e14f4055b5f93e59c07998077b7dc410a221d149ab6fd9d7e2f39e0a0318f7692d6246397f5e28d343054edc207b0a109d96752f1aa2e515bdedbe66b76d9ba686be41ba1b7bafbcb10a55c6d64a7332a53bc5401142f73b7312183a5f26f3758b959139a7dd1c77f190a0c1a62ca634f5d245a22f5259307aca5466dba517143431d319ef0f17c97056e143a60d54b4012c3899063c248faeac331cab5c8d52d2c7ca08543bc969018171f14afd40579e2964b1488cd72db78abbf76c6420c7663fe333988fad74c16d15dff2e0179a13f6482a203c57e0835b1292c7e9407e90cf1c9b6a8e925de2e94b23b556f8dd517ea1cb9dbf5b8e3e7b37a75825189bc2da93d91d0d4fc001afacb8a9aee19407d04d4ee0a87bedc7814600a5b1ca5dd2d9b763c9571158c17792d3977839b67b78237ed371e433ef51746becc410f8c4c8ce8fc75857568304505caa527679e9124d3b950fc34a358d86c71c488e22fef5b9f13ec02333004ede26f66b9dd31ef5478bf9d9f9a279db96d2b2798ffd90b9f88073332de6321f13f498bfa24c7d7d657a3699e8a456467221390188cf127b034dedd88e64d1c595ac1217a335bfb7e1d136f87acae17163dd81997997aeec86c8510f4e6a4293d31fc61e96dc92915917e2a9479b41f1312615015ee6fc99669977f2bf62f0115f6f2fead7ef0fcde3199782d503e25f064d42968698d18cc5faf2dcd4c820b6f4241eb0d8fa2d7f3a67f37b6efec872eba2f121a8ad6fd19790a9e81a1012fed2cb7a51927fb055fa243ebacfd9d34e263270da45a07d17ecdfe9e8dacde119470e3335af87d13c2df1ab37bdfee41ef292875890513bd2d054afe9fba3e2ea0a5004a585eea3a392829bbf9924950e1a8f19c8a89bdec7a4d79123458150a675bd0086bc0e606328e1b2d90db66f5bd09b1d0d25f1c23d35dac4e333daf1dfc2b86593c87d7da7ea5f0fc7b2d8316ca6411bd33db11bb20f4e1e7f722401a281d0ec39ba92fedf74ac289c16c39ba916320b900112763ff4cdef5d37020223e1db498730bdb02c6af8ebcefb5278757ce5d6cb334ff87180a23461738162d3051373c6b97bc861daf86b0e81cbb150838618a31e9555ab7e4131a787e5a0c45a10801285cd1304386aa98dbf01a5414b36e6470c7aba836ef357f59d8550268c93f11cfc514093176f596c163165dd736b0272cc9044bb8015d0c06b63f25294a68ef20c7aec7ae1c8ea269751ce4b07c62cc70d0c10c7b060a8629285c0213aeaf333839e428f8350f838f2cd7a92dadde11833196a80bcb361ac6ace41c636b29633940b14fd309f235c195096780167d3d7f61675799c574ec8f87630cd68f46920207719aa96180053eb7426d74d43b400a9bc9635fec645eca84500853823429707819c2df8104d1a901baaaaa82db848bd9c1364ba031eb3634c71d38ad5910831edd84d4c557b4b08f1867ca289c598ac07557c748ab5feab8b82473dab68251ae7bcd7c5647c6d5304311af4486e62fd323c142fb97da8209002da62d0b9c4e83c955be1f41b00cd156e8b8ad42d8babe671df8fede1ee503232106a8069ec3de80432914f60836d20137ab8fccdd1cd0d517a83881d7730de622b7780ccd4366de12bfec1e8c34b0866c0a09ad91ba0e824ad360d821415f680c0a2befd66f5571e8b41772764d328c7db755693d38f27a22ef31ed4dc8405028d31e01fa2652b98e57f431296888f183f6f5be175647e6dec4639d6db8409f1d8c9c029735249ac3895eed4874b9f44bc2af56ebdb8b0517ecdb69134573881a0fcf9f089997750a924a42a58ee70848297aed999ec8cae01e0817db88060e0571ad7f04ec21db8d1e09168c00ea301b237c67fd8a20f32312e2b08cd8321108faf25ce1c6cbe090d143dc20031b78b474d23d16066ecda03739aebf5679c814569ed46af286d8843a6cc6695a80267812bbb4a65b79e36ed365a6e7f38e3e0be8ffafbbe19fbd0f8d7aa7c6182f34f7a98c09b3c1fca3d8c3045f371b2f67251e1ee8c65847410fdbc8c25a8911556b3120221e42f826aa3f9e5494b645250553a33a5d6dff0d923ca2a72822672bf340c1f2120f0e23bb467241766b42232be23e92fb1908df039216ba35db95711df908ab6485a9bba4d5a87bcc4bd05116fd96d22e85e5d6c4082bbef33f8a9599f096e26d596331432b8c961cf9785b0e387d9989be6bf719b761cde20ca1c281b3a701fe1073b4173e2de4194cf8822ad8b7de42b8a338b81fbddcf7577883879b32a40065ad0e2a185a7d16b27130008b65b216b04481466561823657bcb5b911dc9c2a401909ded3c1ecacb90c9c0a3cbfcb83f3ce16e0824806dbc962fec61364e37a86846ff10f34d56114606c256ccdb004b77daaae2dcca4d0b485e79e85e0498f22d2b796a589fb50c656bf1d3fa8227361343d20567a376fd9bf75788d4c2c62492132e9c8cf8cbe69f451062728b673016f2a3d4eeadf5b45c64d3495b0745742aa9c3d967f2f45a6b4062b87fd9b08573a0cbcc91ab6fc3a1edf2af377640fd7da945d06d25de440b3d8030e1442bd08c23cf8c8751ed57bb44d92693c19a677d1dc4ca5bd1a8c61fb350a9522d45fde3891e1a4e42d65b3cc268bc5fbea6be51cdd625b0288b4854d232b514209b5025fc499f2a2dbf5ca9b4dcfa86adce2c04d67fabdceb651fe00f42722a0efaebeef556a81bd9fcd4dddd0253bbcc4572ad366a826e7809bde043e2655337bac8a5010a8e47cf362239c86eba9fff5f990cfaa3207db96c424ece11284e9c4cfd5ee0ffe0cdc22cb4b0cb4f0497643ee90fa455184a0c5445be0781fd0327a4f99abf01978729a78aac72e6bce4f800b2c161fd520ece0c247e5901f54d65b211f28497ae07bb3b1f9e01954a9f5992b24811a107be00011a26dd0022ec83d890760c7c2ba53b0d1814a97820ebdac057be4844c0adceec2d1b167100cc4b883042951639a04cd145d12421d5a8981445520aead1ba5587f6d84ec05377554914556fbfd22bc791426acb934a1c05b9db714c0f5e89783c25634111b86469c041a12d6c754fd275672ac4fd7fdbc9e08a52fe330be346527bbe81503b2554114aa2257af6b19f503f7b144bfa04f009bcb8775056abe574f87fe130847581f87b3574906829ff45b6261775c4d4cde8a8ec7d1ea9ba4266da0249801f64f47b80cd82f1fffb91355ad5352bc6721be76f85afcc95cea9e915e42751d48df16425f7c64e51cbb16208a865413c00e3edc08e7664a8dd5124fafcc751a8b758727e3949eb6e998b4368e0516ab575221e76701aec8274230c792c222217fbb799ebb55bf323c1701fd082d195822034f84c0e328e9a59d7cdd54c85026d5637123848a858ffb1b15e38a1dd075b3a459825a7a28ff99180ed703d79b1dbb81194e04b890fee7b8e3e83368e2c1fd9c08498533e1659edbb95b95212e216fd62eb14f71753e05ead6589239ed51b459731393dcb773b2237854c41bae1c16cb6c4bb645dfb574de656237a7296ca9878a3673ce8990bf543b9d0c12ac1ede30fe923c6d20be7662a0d0e4a38adaffe36550f397dc134d016d8ff980100502b0f39e4965023b7c3b3af13c715c27eb92f52eb1d1ea03d1c03be14f60ce0fd8e4ac03f939b2ce46c0a01edb02f25ca0c0ea42f9dfe809c092557f31beab22311d06896a390c81ee29d9e04cae3ae900307878f58bbf25126d195e38b426158483c1f1e9ef7c902e4bfd0f9c55eec465849e8528fa93873c49eb507376b12857ca9dc18297fba6ae7a87e869dbc2836eee0d87670f4fa76a4c34bd546a5711807ebe17933f1d48bf83fb802743657e432655587833322156c82a0e81ca7a17c494b8d8caae91918133b56bd5a39b8cf1821639be28d7ae328843567c448919124d83648063edea2c82a4cdc631492d0ff9272c3f48e6d764a37eb46b0fa826c0d89d84dab0329281a30afc436a38501e447f405e2228de9722dadb710ee212f5cd5def856e1620f452f1b1c87c99accaa5a582568ec5bb2312ad3507aae82c9e51477dbd662726c68b2d14ba8471d6ba3a99441a3ea0560cc5263b0f729d11963af53bb44db5f0d58d430a82ace1bf46f353ea9e7773181b2455477b81a324f6910de1a2a5660ea5ed1a2898d690172d9e6f112dba6616af5750ccea74c3170577d594c335a412b11e5d6e6ed68e121b7e9cf290da72b97e1de4f0e5b05e28671d66e16b35293d9661a5ec2399e1b3371617b2f081c3d151a93fd9b2765f05afa3f9c804a47aa1bc5360244e072115dcc757cd089be47f94282f4ea347e417a7a09caa4e7b27f26b077d78574e929c59fa46bbe952386998f4b801b1c3741b97c4ca89df3be88ead778f1c1a6b8acf8d89ade02bd0f4087014038b8c603914119b4f1f2dd85a60ffed60f077e185ee096f503ccdcbbc4f7536c3a40abf942534b3129f2c4d48b1c40cfae6aefc3a1fc4edcde068812c95e4346ec5f3bf792e7e79b33f5069bf3d3a38f9cd0e695cd8d7df15fba8820280e37dae622435f1090c6aff3676f8f9c6835b12db35f1dad19430632bc48190b3820465f381d19c0d25a225d743b98e22f896675ddfac868a84c10de3c08bb879ef68053834b75b209d7d2b5b940f6556b33db43abe2e7dccde728594d43e3b3374cf51d00d55301ce63c7304188ec2d1dffeade768ba841f036195ad0a5e56d6819b5bfc9f1bde1bd6273e3067270b4952db3180d3e11ba1fbc38878b57e866066ebd964a60315021dbd9f8ce7615488bdecf26732a657a97121dc0e71b7a2ae9bec2cb1bacd470d8df4153ccd25314e885be1b61a84af34d7b9c2bbf18f632c81594ccb92671a1f06991ae42cd0efaaa7ce5e8ff8420be51526fabaf3eed5a4bbd76b5936d8ed1a8cae7a2a2a073a113a46f6187225ed841a5892e1c259d2fa85151af18dbcb61157df91a0106871694db8b21d2ca384903fa10969ca1ce6d4a85116d39a0b1a2a9c5098a2d510c6ee15fef9ed61bf1d7d2df7673e2dcc3a37bd4beaf7344e2c0a1f01dd0c6bf05c58d82e33bd1b8e50c9dfe5dfd28381771f840f8547a4ae97205b2e7b0feea00acb07650f886ed10719bfd7526b1bcb47885df11adc720189102366f087659d617efeff715f82c271c6faf35ab3aecf3af58e1f1d507dc6fb2054e65fc26d9ce18da03336cb1225e3fc9a742f9d4dc4d31ba0b38f98fb4c8f189b5383795d0b94489ee507b0910d167ee74c2b9ef6abbd95a63574ebd307140efbae3d59a47cc34233d214c8206769385682b134653792796d0b7bb7c9725019323f9803851b4b82f4408771caf5f32c4d820de1254dade69f986f72ce655104e396cf61b531a17043b1ed61c862c4557295a265c55d928721ea03f26395722746881e318a3247a67d991e5367c5e0d27f763c0c8b9ae98da21533b9349bcb2c866e8d6c2817ee8c289e679e112cdce2630cb4659a661765b53da0f2eba019113fcc5d35042b7733dfa1a0f4f4293edcd7498a59095f0f7dd0f69383ace4e70b94066de05000e457ad0e847480178076c8e11fd59c5cb2f4c4ae18cbc29de0127beb7f7d09e4e70a545860998aa357c0a98a930b17423de09e9bf2c836975a04984aa1b23e15655a38d46be2fbbc7ea8b8e6ee5aef0aff5defc62884455c5d28b85f4141cdd20e88adeccb3036e8231e61f2fb2cdee5b76f36db7b563ac44116e5782215a2dc315b6036a8b5479041bbe9d284febb79238c16152d926176e9079cda4a199aa8e2191127aed01772940f9bde39e9d679279a568acf825c9d872a7e64627d6d4793cdc00c4292c8b22941e40679d3ed7242ed61184f8016f4c91a77fbcaeb64e9e2276530f3ed9c53dd57c6b70c5d532919ef31cfbd6cb58d502f92cc48f7a440dfcb3f752bffd5707cb6732b31d9a2225c0293e7518e0e771a0746565220ad9cfb9f62a650cd9ba4eadf536a24884c0e238a211eee9ff3b18d140bce6ebe903302494ba1111c23946be7cb07285132dac658da9743db03c3b912afe729d887514c0949f5c2c764aec634511f650bec1fe67a065de41196de460f2765a27520f6499e447d1668f5b9600b213d7e145f9aaea45f7e599970200a2a86b06625571ecba20e1d979cfce0f298c775efe7a4be1630b9aa1a6a5f3c6523c4d01ffccb6a01c38123d4cc75ba480e9be9bf46f1a43e2e979b62fa4ef2a1248d16ef5b6b7ae3251de269e4fec94e5e5ed659cb2ff7e3d556ac9a34f391fd2668dec15a3695a958e996ec34b8404e5d145476403e237b3406f120ce57abfd17abc99daf3de2d70c8bdc82e9ee0e4781f3960751f07bf47411e79a1464646d", + "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441156615ed204aa948509f830e7e8756e609e419f8a6f8561fddd9202f8abcba0101cad4adce90c01d548eb5a88e3935668204c5bddb827b618a40626d8bc1281f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000203219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } +} diff --git a/circuits/benchmarks/results_insecure/report.md b/circuits/benchmarks/results_insecure/report.md index acdf68b6c..86fb40d6b 100644 --- a/circuits/benchmarks/results_insecure/report.md +++ b/circuits/benchmarks/results_insecure/report.md @@ -1,9 +1,11 @@ # Enclave ZK Circuit Benchmarks -**Generated:** 2026-04-27 10:35:23 UTC +**Generated:** 2026-04-29 10:02:54 UTC -**Git Branch:** `main` -**Git Commit:** `e651f30205117e83a9cc48ac44664d434466724d` +**Git Branch:** `feat/benches` +**Git Commit:** `36c01c62b86e2527279842280337f2f4724d2487` + +**Committee Size:** `H=3`, `N=3`, `T=1` --- @@ -13,36 +15,107 @@ | Circuit | Constraints | Prove time (s) | Verify time (ms) | Proof size (KB) | | -------------------- | ----------- | -------------- | ---------------- | --------------- | -| C0 | 6847 | 0.12 | 25.76 | 15.88 | -| C1 | 57818 | 0.33 | 26.00 | 15.88 | -| C2a | 142625 | 0.77 | 26.58 | 15.88 | -| C2b | 198355 | 0.86 | 26.30 | 15.88 | -| C3a | 132633 | 0.79 | 25.93 | 15.88 | -| C3b | 132633 | 0.79 | 25.93 | 15.88 | -| C4a | 92515 | 0.49 | 25.95 | 15.88 | -| C4b | 92515 | 0.49 | 25.95 | 15.88 | -| C5 | 151717 | 0.79 | 25.87 | 15.88 | -| user_data_encryption | 53732 | 0.32 | 25.68 | 15.88 | -| C6 | 86927 | 0.52 | 26.68 | 15.88 | -| C7 | 104273 | 0.49 | 26.20 | 15.88 | +| C0 | 6847 | 0.12 | 24.97 | 15.88 | +| C1 | 57818 | 0.34 | 25.84 | 15.88 | +| C2a | 142625 | 0.78 | 25.50 | 15.88 | +| C2b | 198355 | 0.85 | 26.06 | 15.88 | +| C3a | 132633 | 0.78 | 25.14 | 15.88 | +| C3b | 132633 | 0.78 | 25.14 | 15.88 | +| C4a | 92515 | 0.50 | 25.00 | 15.88 | +| C4b | 92515 | 0.50 | 25.00 | 15.88 | +| C5 | 151717 | 0.79 | 26.28 | 15.88 | +| user_data_encryption | 53732 | 0.33 | 24.58 | 15.88 | +| C6 | 86927 | 0.52 | 25.34 | 15.88 | +| C7 | 104273 | 0.49 | 25.42 | 15.88 | ### Artifacts | Artifact | Proof size | Public input size | Verify gas | Calldata gas | Total gas | | -------- | ---------- | ----------------- | ---------- | ------------ | --------- | -| Π_DKG | 15.88 KB | 0.12 KB | 3037849 | 179452 | 3217301 | -| Π_user | 31.75 KB | 0.22 KB | 2972953 | 340140 | 3313093 | -| Π_dec | 15.88 KB | 3.25 KB | 3549211 | 188232 | 3737443 | +| Π_DKG | 10.69 KB | 0.41 KB | 3037922 | 175616 | 3213538 | +| Π_user | 15.88 KB | 0.12 KB | 2973073 | 170272 | 3143345 | +| Π_dec | 10.69 KB | 3.41 KB | 3549077 | 186764 | 3735841 | ### Role / Phase / Activity | Role | Phase | Activity | Prove time | Proof size | Bandwidth | | --------------- | ----- | -------------------------------- | ---------- | ---------- | --------- | -| Each ciphernode | P1 | one-time DKG participation | 3.37 s | 95.25 KB | 96.12 KB | -| Aggregator | P2 | combine folds + C5 | 0.79 s | 15.88 KB | 16.00 KB | -| User | P3 | per user input | 0.64 s | 31.75 KB | 31.97 KB | +| Each ciphernode | P1 | one-time DKG participation | 379.38 s | 127.00 KB | 128.19 KB | +| Aggregator | P2 | combine folds + C5 | 0.79 s | 10.69 KB | 11.09 KB | +| User | P3 | per user input | 0.65 s | 15.88 KB | 16.00 KB | | Each ciphernode | P4 | per computation output (C6) | 0.52 s | 15.88 KB | 16.00 KB | -| Aggregator | P4 | per computation output (C7+fold) | 0.49 s | 15.88 KB | 19.12 KB | +| Aggregator | P4 | per computation output (C7+fold) | 80.31 s | 10.69 KB | 14.09 KB | + +## Integration test (`test_trbfv_actor`) + +### End-to-end phase timings (wall clock) + +| Phase | Duration (s) | +| ------------------------------------------- | ------------ | +| Starting trbfv actor test | 0.00 | +| Setup completed | 2.98 | +| Committee Setup Completed | 20.25 | +| Committee Finalization Complete | 0.01 | +| ThresholdShares -> PublicKeyAggregated | 379.38 | +| E3Request -> PublicKeyAggregated | 381.92 | +| Application CT Gen | 0.31 | +| Running FHE Application | 0.00 | +| Ciphertext published -> PlaintextAggregated | 80.31 | +| Entire Test | 485.79 | + +### Thread pool (same process as integration test) + +| Setting | Value | +| ---------------------------- | ----- | +| Rayon threads | 13 | +| Max simultaneous Rayon tasks | 1 | +| Cores available | 14 | + +### CPU-bound operation timings (tracked in-process) + +| Name | Avg (s) | Runs | Total (s) | +| ----------------------------- | ------- | ---- | --------- | +| CalculateDecryptionKey | 0.11 | 3 | 0.33 | +| CalculateDecryptionShare | 0.61 | 3 | 1.84 | +| CalculateThresholdDecryption | 0.57 | 1 | 0.57 | +| GenEsiSss | 0.12 | 3 | 0.37 | +| GenPkShareAndSkSss | 0.22 | 3 | 0.67 | +| ZkDecryptedSharesAggregation | 8.54 | 1 | 8.54 | +| ZkDecryptionAggregation | 49.65 | 1 | 49.65 | +| ZkDkgAggregation | 20.66 | 1 | 20.66 | +| ZkDkgShareDecryption | 1.45 | 6 | 8.68 | +| ZkNodeDkgFold | 78.08 | 3 | 234.23 | +| ZkPkAggregation | 2.19 | 1 | 2.19 | +| ZkPkBfv | 0.33 | 3 | 0.99 | +| ZkPkGeneration | 1.34 | 3 | 4.01 | +| ZkShareComputation | 2.65 | 6 | 15.91 | +| ZkShareEncryption | 2.47 | 36 | 89.00 | +| ZkThresholdShareDecryption | 6.20 | 3 | 18.59 | +| ZkVerifyShareDecryptionProofs | 0.10 | 3 | 0.30 | +| ZkVerifyShareProofs | 0.22 | 5 | 1.08 | + +Sum of tracked operation wall time: **457.62 s** (often much larger than end-to-end wall clock +because work runs in parallel). + +## Raw circuit benchmark JSON (Nargo) + +Source files for the **Circuit Benchmarks** table. Persist this directory with +`crisp_verify_gas.json` (and optional `integration_summary.json`) to regenerate the report without +re-running the integration test. + +| File | +| ----------------------------------------------------- | +| `dkg_e_sm_share_computation_default.json` | +| `dkg_pk_default.json` | +| `dkg_share_decryption_default.json` | +| `dkg_share_encryption_default.json` | +| `dkg_sk_share_computation_default.json` | +| `threshold_decrypted_shares_aggregation_default.json` | +| `threshold_pk_aggregation_default.json` | +| `threshold_pk_generation_default.json` | +| `threshold_share_decryption_default.json` | +| `threshold_user_data_encryption_ct0_default.json` | +| `threshold_user_data_encryption_ct1_default.json` | ## System Information @@ -60,3 +133,8 @@ 1.0.0-beta.16+2d46fca7203545cbbfb31a0d0328de6c10a8db95 (git version hash: 2d46fca7203545cbbfb31a0d0328de6c10a8db95, is dirty: false) - **Barretenberg Version:** 3.0.0-nightly.20260102 + +## Notes + +- All nodes are executed on the same machine in this benchmark run, so inter-node network latency is + effectively 0. diff --git a/circuits/benchmarks/results_secure/crisp_verify_gas.json b/circuits/benchmarks/results_secure/crisp_verify_gas.json index 3d47aaccf..cf6816e9d 100644 --- a/circuits/benchmarks/results_secure/crisp_verify_gas.json +++ b/circuits/benchmarks/results_secure/crisp_verify_gas.json @@ -1,13 +1,82 @@ { "verify_gas": { - "dkg": 3037824, - "user": 2972929, - "dec": 3549028 + "dkg": 3037922, + "user": 2972869, + "dec": 3549077 + }, + "source": "folded_proof_export_plus_crisp_verify_test", + "artifact_sizes_bytes": { + "dkg": { + "proof": 10944, + "public_inputs": 416 + }, + "dec": { + "proof": 10944, + "public_inputs": 3488 + } + }, + "calldata_gas": { + "dkg": { + "proof": 170028, + "public_inputs": 5528, + "total": 175556 + }, + "dec": { + "proof": 170088, + "public_inputs": 16676, + "total": 186764 + } + }, + "integration_summary": { + "integration_test": "test_trbfv_actor", + "multithread": { "rayon_threads": 13, "max_simultaneous_rayon_tasks": 1, "cores_available": 14 }, + "operation_timings": [ + { "name": "CalculateDecryptionKey", "avg_seconds": 0.599410291, "runs": 3, "total_seconds": 1.798230875 }, + { "name": "CalculateDecryptionShare", "avg_seconds": 2.123328597, "runs": 3, "total_seconds": 6.369985792 }, + { "name": "CalculateThresholdDecryption", "avg_seconds": 1.93815725, "runs": 1, "total_seconds": 1.93815725 }, + { "name": "GenEsiSss", "avg_seconds": 0.755760708, "runs": 3, "total_seconds": 2.267282126 }, + { "name": "GenPkShareAndSkSss", "avg_seconds": 1.230714874, "runs": 3, "total_seconds": 3.692144624 }, + { "name": "ZkDecryptedSharesAggregation", "avg_seconds": 18.895682083, "runs": 1, "total_seconds": 18.895682083 }, + { "name": "ZkDecryptionAggregation", "avg_seconds": 48.057542125, "runs": 1, "total_seconds": 48.057542125 }, + { "name": "ZkDkgAggregation", "avg_seconds": 20.904339167, "runs": 1, "total_seconds": 20.904339167 }, + { "name": "ZkDkgShareDecryption", "avg_seconds": 30.160204763, "runs": 6, "total_seconds": 180.961228582 }, + { "name": "ZkNodeDkgFold", "avg_seconds": 102.337581166, "runs": 3, "total_seconds": 307.0127435 }, + { "name": "ZkPkAggregation", "avg_seconds": 49.016015041, "runs": 1, "total_seconds": 49.016015041 }, + { "name": "ZkPkBfv", "avg_seconds": 3.839788277, "runs": 3, "total_seconds": 11.519364833 }, + { "name": "ZkPkGeneration", "avg_seconds": 65.134843083, "runs": 3, "total_seconds": 195.40452925 }, + { "name": "ZkShareComputation", "avg_seconds": 52.426543555, "runs": 6, "total_seconds": 314.559261334 }, + { "name": "ZkShareEncryption", "avg_seconds": 112.963847905, "runs": 54, "total_seconds": 6100.047786911 }, + { "name": "ZkThresholdShareDecryption", "avg_seconds": 244.367978902, "runs": 3, "total_seconds": 733.103936707 }, + { "name": "ZkVerifyShareDecryptionProofs", "avg_seconds": 0.092927916, "runs": 3, "total_seconds": 0.27878375 }, + { "name": "ZkVerifyShareProofs", "avg_seconds": 0.266464458, "runs": 5, "total_seconds": 1.332322292 } + ], + "operation_timings_total_seconds": 7997.159336242, + "timings_seconds": [ + { "label": "Starting trbfv actor test", "seconds": 0e-9 }, + { "label": "Setup completed", "seconds": 3.274390084 }, + { "label": "Committee Setup Completed", "seconds": 20.259594916 }, + { "label": "Committee Finalization Complete", "seconds": 0.005869333 }, + { "label": "ThresholdShares -> PublicKeyAggregated", "seconds": 7204.022842209 }, + { "label": "E3Request -> PublicKeyAggregated", "seconds": 7211.068496417 }, + { "label": "Application CT Gen", "seconds": 7.746761542 }, + { "label": "Running FHE Application", "seconds": 0.088362083 }, + { "label": "Ciphertext published -> PlaintextAggregated", "seconds": 814.168040875 }, + { "label": "Entire Test", "seconds": 8056.619484583 } + ], + "folded_artifacts": { + "dkg_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000830d9d4344316b026000000000000000000000000000000000000000000000001d383081c39dbc5a000000000000000000000000000000000000000000000000ac70e435f22d64fb500000000000000000000000000000000000000000000000000005bbc150f125200000000000000000000000000000000000000000000000a8a546866290bb770000000000000000000000000000000000000000000000001fd3f2400d703cfb700000000000000000000000000000000000000000000000b9038d2ae3e79290b0000000000000000000000000000000000000000000000000001e3d48d51e5500000000000000000000000000000000000000000000000067a0471dd42faa6b0000000000000000000000000000000000000000000000000e9084f4ea2d5e512000000000000000000000000000000000000000000000008a356e94c183365dc000000000000000000000000000000000000000000000000000254af5f427efd00000000000000000000000000000000000000000000000238e18ad2a5a9480f00000000000000000000000000000000000000000000000bd3b65543dd7dc02f00000000000000000000000000000000000000000000000759321a99ec5a19300000000000000000000000000000000000000000000000000002a525effa8d9000ee44df0d016c13539e3e1de25cb3283bfa0110644e6c3060b51acf455c43f02d5202ac66917f20fae1a39f8cf51134df47884f67caecca680f87bdfdd85ccf0315bef50348a88d4c79a1b50bdc50c9882a2946c73cf72c563058759727f8a009db15cdba20a346d9491fdfdff4ddaf05c2474d9c1f2c4821a5e2e101b7b8e82e181958e78629f078e836c725ba08236958e3445a0dc31fc4c2202707b61c7d0ac53aa35319f776db882a6acee6b04a492720c30b527f6a209efbfb4b22975403a5568ec8e19525b52dfe82dfd9aaab141462570f5c39f9a42f13700ff87603118b076682b92bee70ee8f9b972b8cdeb9ff1fbd603352f945f2c95fd35184f70f989616eff536ee31d0349dc97067aa11f2ab4c8782c4d19a4b89968e13f69f208509774cc987cc232b93c9c49974be00e3ee21c6d743b80d823f9eb1ee13be236cf0e7b7aa0a5a5f4207edc057a37096d17a63c48f2866132c681a904108c02045139ff715913e4d22a696f788d1cb2424d855ef9bfe36f67721de67235cab0e4f4cce9ff0f3588aca137e0740c7dac2a980816ddc38f10be0dd37f01028891d4476773d637a1bee280492d73d68838af602126de7b85d767e835f1ec2f5f7015609620fb34c0980312b5b7f67ba6ad756f683152cd1a95e9e4c9a8fd58bbd1c0b2d262ca7d1cfbfc729424917aa0bccc6e667b7d4e4293e56552cb688b8320ec6d51d706a3d0b516eeac14f7b49e736cb687e82d64d239005709ea7a22af41daaba74d8165e869cf52616a224d38bf14b43f9365e25bdb8f5e3088158cc3e2ec485c6affc47a2b1a4a1d0b691d81aa7efeb0d4f243c3f9862a9b376e7648a2a1f40a23824acd2860b8fd4464a89ad9da06c090a2dc69564011c9749dde2ed15a551e0c27cb57298106bdf016afc08b87f0ac06032ee6860c10be94821fde507c4f9ccbfd67261a4729466f98ee1db61592af1fc7b39e2181034e27abc492409e069c23c577f4749acd5236e349f1c92837155ab5553d1ce276d8aba649f661e4ae3dcd8f73ba139ca807d90d6dec1a9b860762731186ba09357343823fd671a0a8440d758f2714b07ce0b6d8ee3e072af2f999efd2b2f4bd29a0b7e4ee2fb03969abdb773917cdfc033166bdd42ee8c0f0de8fdc1f0b959ffd56c806c06ea1137b28ee248c3176911c6a89f3ac4fbe9294fd2c25740790a660a831c1fb96109efa0ff705b5c893a9243584fbbbef285f05ca9370a3a352ff33e3fbb4ce74222a57e9df2068cf76844517674c6e6a188fa7158768ee6fb34da4c185fb830a8030b0eff418ff974072732b830d30df3199387ea05c52692283f7bcce83b46392ff77a2391ee371a20d92c00b3e9ce77fdd50918e3ca550e914a7a53ee6f8b7709d5a71495d8ed3e4500f7d429da6dc0ce8b1e10e8153d28ed7b0454f33cecd924540395148ae0936911fd4c376a78890ebe5d7fb220351c257b7bd4569d752023276726c1d48dc36a0147a3db2a69a24b00b54e87d42177e95503de125797ab2420f3fa31bbd5c0e70f3038b55ad7e40fbd4380e86fdc7fe89164eb0aacd59012dfde37496f6116d41ff33c74efb86de3dfa2d24cefc0b63c89d79e133cc29905efb2920c4f7da9c8b961871dd18fd44999a25e5dcccc9ccab601a2e675373e100c397861eb058b5755e03a51eae9d52c2e4d4995ae4ca18e4dc2233d7d7aef09e64d43b4813625ee86b3dde7f88897786e1416eddb163c124b159785245e69114691c2e2133c527da43f96a3ce84e6dd4ca5565323c6c315ad829d67ffe1c404621eb8bf726f2e29a09c7859bed166cb8ba83b62b89937330ba87944cfa8ca0ca6890ea5b94cf33b92150635f7eaaa4f6ba748de2c1511f5951f64b2020cc62dd083cfc17c88a46303505006aba555321be0a57109e342280647134ce385c5299579a2c5323a9de3f476deb15b2bef26ae534a4cc8ef85736d2e278da053c606e1876d5599770ec050ca34a7586b97509498768869afbcce36fa99b3bea7e2190eff69b5e545803434ea8ad62014852a371430a727701311a6f04fa47cb2cd08ca37d24e1311f454ce5d64f1be459f3f63bd3c2c5d2d8b894886deb7403c1915a57f7b0dc00c079803ca7502bfe4818087b1bee5e5ef561924cb46df8ee9af2f4791d0d4821ba79925efd25af9808cbb8277cd45e6c8b1c435290fc3a81816113cd7b0348fa54da05b8a621dc0216d78be0a5d5e1a910fdc581e4d05f27a011ecc21fad91def43ccce7539527630fe9efe81a8af34587cb9fee87f922e63d01377a702022f407844e60f563192d097fc190d4b9423e4e7b237edbe025c47b910c6da28d26c5f25a5025265d2a204a519b833f8e64d2a3a4c0f00c1c39ce69e1d0b89313a4d0a35ddcdf13ffeaf15535473b98771e39baf7e4aa6f927264e6119206d1b024b808af816db984825a1ab0c4ec9df14120dbabdcdf4b0bb4445ac022d4f53f6757cec1a02719b166bc272aa26fd3d5a19f053e13fbd00b5d67ada109d29051cd5ec728a99bc53a016164989493cef0a3fcd26825ad0673bf2fd9a17788433a5a33f5dfa3d26c5afbc72d8154c7ef45b0321decf426bc6f37e7b0e0493ee9e522db3775ec83b6d4c69585fa5023553e5d477f6e1ac2a80b4f0477a0f18b2c4014e7596d55b3e6cc268d4b3f0d265cf823feb97355ad804bb1510c5021956e6865c693615eccaa18c8dfd10fd643ae26d30bd4fd07af6309c8385af2ae91ffade4e050bb2a85681ec5eee4e55168bf626743731018ec69c8ff8574700456dc0c1b55946cfd78d2350072c21be9d3081f24bb64349c2dd8f63fee8440c5a2c18c8332898034b2f6b5c774f71d8a436168330e2a43d1501d35bf7264307009ae8c13c7f98a61e2b6294ebd04b54eb61cd67c868e5a70b247a82c56b5000773850ad4fec37329ce608029bf0091939a6a1b6b9f426f2042c0717b61dae1a416763e0be43ca69a9f855685aa38ca1de9230cc19b7a4defaa050052549512770183df9e2acc5a1723ce3d73b96b32c41adfafe5cee370a1e678fa79ea3722461dfd9aeb45139569f0e6f7a3c3d7f60013fa59ec8b7345fa311351a12d2140d8e6ed91a51176926a8dba35e2c65d4ac7320103427b36f20f3411ba8f04ee614427ff6b94415c230ed5f49545dd15a4e1df3fed50437b81ddfac5cf1165e6116e3e7fec6439f5f56494929c6fa96e7e6a49d999026d174126e0deb9eb11aa01cd1e0dca8ffee2d57bbb6a22e1393f6ebd5392244b30634971e9f38de5aa999134af1bc04a03e028bd552b71f42a2b798e649db9214c69412e408467037b7de1f4fd334f1c9f9c7bf1050182d4cb55bfa65f679a1c01e10cce60b0ba019b0a7211b9f3e4e5cf04297d83eeb51a0d4582534a00decceea4c163271f2696053e8164d2dad9506d5bfcb921ae50e0d91b96b81d4c3a805116e90e9c4f6becf24e42fa10833dbf0f0713f1b46fe67f689ec0b3d6e6ae54838dc2b20549c9fead4f317fa104e25740c58fa1089a411c6fe1140e07cd5e859dc3f4b10cad565cd35c21eb743d7d066b0216ef1222ed15d5d2b19901623f0ed9ade841181ef7384ed412f47fbb67ab1620be7c439652920a57f0e24e0489622a90ba284b0f15d8708f105dd4dbc8cedd61f619f19696f3d65d947ac5a37117e42234a0b1ac09891a97d2045fe954f13a507dc665b6f4dc1af44dca049b48f50601239d54963830057c21fea7fbc790dba2a482930e983d06cf20e52f841048ea23fd9becae3c6c56dea16d3627053072fd2eb637138bb5af7f1574e5ea375e8d147294672d93b1ab92a2e625c96a55982d59f2908793089c5d675fb63e56ccdcd0872735cc0c45351970c34f093e20663390986b19081d84681c360a40344a48044e228a23139c07de62bc0d25c0f844edddb2e17b82340e9d73f228772ee64c59f9746aa416f1405860bc6bfd996c2e61c9bc823024de7bdf863bc5133fd6ab0805c4c88ebbd3fcbb12d0f7308c4c486a20860283e6e2320e198f6a2d085cc8980e26f2e51a550933928e561229bfb72912cc955aabeea11b030d1c17551eccda5bb5f5bff83fbbd5013563d0f8a86a2d65ad84d5c95ce6c5a2b656b3b578b73f21d02ba88fe8a9d712e2afeeb9d7e0eb9c1a541f91ade3049ca1f51897a474235342a9a6f88fb499428e9770a22b2dd768a096dc5616a65630e49d6805da5c884ae7e0312ccf8feec24843bd69da995e08aeebb8e5a4c54b61d70edb1c5e62db5e3ff429ae5cafff81dd26c2cb92f24909acd104662f7d74d54466c57386cb437cda86fdbfa342f3011ac3251f702fb97585a11f54408b29243d4eae98f77a096a0ea94e624d152b8267e3d7dfeac3d7df0e8224a2f2d99102031ad8a74dfd347c88c55de823733b90632ec5a50f12be845c37ae121d1b0d662cf8961ca1227bef498feb4928655861f5672914a9fb0b568580a74142716cd5ebb0ce51c1c8d072f6dd5c981ca3ed106bef9c00c32e0246166d0d789aec5041f57d670fb2f0fbb4aa87335a7ef7a512cd1a8bb26b2d343de10f1b05957a69cb3e99e955b9aec21c4fbf7a4b5453c421bc106f05c610f438528f8e733d48e402f42600c1ae3b74318c41b722dd5cc6925154ed14a9928b5a96e2e4b4efe986e226c755e98e61ea76ec944eb78a3d69201231ee7b8063640dd0cd244ae2e598bded49282ed4d79c0f890c098432a534708246110b4e213240c5bf0026fd920a4bb45e2c574295ba581b644d13d762cfd0d43d638af1e48c7e08246e03fed8b6dc6c09ab358b627fc13faff5add1d19751abbdb7ea60b18e3f2b102fc3d30167795ea71badf50e36e7ae300dbcabd1216048274a5622365a76c5e7a50d353fb8e9a1094f8deb532f930fea082eeb6a4b31c1bb329608eefae298673490756fa62d97ca75d15f4441f1e6018de13991f3816bc02756edccbeaf4300ebffada8d6b6c943cae931a17f6a89a5e2b232117c0075f297211fe6a9cfdd0a4f32127175b900f81e70ef7e79e1d1e51e7afebd95a0c91f87a48820ad1236710841d0f4cad093f3173a2d3060d59d33d2de467f0072a5a51e107eb89a2b8dc2ecd12d77db3ec7513ac16154c2f1ce91861514e615724f19f85a4c2c2b99629eff7eb549565ad3f5217d6ed6b00eb83c75e170215ea04b957bb50d43308a0e5993d64b0341182bf7e615835b8a971f1d37d18630b46287d062a775a49374c26263f01e4062cfdc3b934fd8c22029a3d44d0760c116a242d2751cff8a77d499e4b9ba267e85143e5f1a59195d98cc13ff0a4fb3ad7c90907b712c497a116fc6f365a7f4f4285f7f5926487491a9cbed80268203b5e53074c7c275265fea6cbd5555f42dc8f8f45122a9f1a64120f0ed5f2243f410041026d88d6e4179b61e5d74d705240cd0d43730cf5cd444824aa68219d38dce9192f1023376a1d43ccf70c0b7382b4253eecb6aa387b83120cdfe6d02788ae70b3303be8647e4498ca34cae02c5fff879a7d4106c8ece7153abc8db46c12dcb49a23c6dd66ef69852617850c188eb1e9f6051bf69841624f9b98c909b54559b1e42f85ee41dfc9ad92b00495f0fcad184d54f6b3d5bc239541e0a4a1b13750efd50ea8779427d2fcc35a52cf61a4786f9ed6f69c9c842dbb60436c1c8fe999c51e2ace7522b27e4b3b8caff8e1a4ee75455e869e24333e541db868e616d6bcc60720e529e44071d6f59aabbc1921a7a28a662cf5756a53fa23bf56fec80b6ed6b90a65fc7af3019b9a937f10a38e6e9f505a5560cd594fa6c42b52db56befdb9160be7f0de83d3abcab2d9efddec09d43cb6da76a733ffc61bf9db3281f3bb6c3a27bcb2167b53f38d25f1e1b85e1a55f53dbaa39ed09dd99da47dc62ac3e8676d2179043618a209e0cf54b7c1d85281897b86b7fc4d2a03faf6272d30339c9d2029841ba7c096a9f52c3ffd13d354f06ca15bc394b99de23492f7da1757e3769419ed503135e7736210e1f37ddc3bcfb9b7627354bd38b55f3f3d326f2e8a761a17da2abd212372bfc5fe8f07033d8bda07733512982a3092153286ef6f95e4df1cf934d31d0566f00c1b1f1186bb66a3b3083c285f7c08b21eee1d2733784d442063bd18b682dd4e90921766318cb642e3789a1cc4a6a191643c49a9b5be21fa004f66731f08c82f2d433f0ea3a5ce0d4fa2ebe5ece4545d4bf75eef7387c3622006f028a52b5bdafd3a058c16068a4d331df9ad12888e64e8b52b12a514c0e51dc2c154263d1399b3108002ff047d94c86256d801891f8c3d0cac48d7d5503f2bb7074d74e23b2bc7056963f5897a95d9dc32006c6a259166474287b15063b900bc8f035a99d7cf793ef4d706050388921536d3b3bac47fdff272b1f34f94800f0b6de358640c1f7f50cd197faaea1afa3dd005abe027f5406a1d43b4fa753e1bf29ad3b1ddb946fc5ad5aab9c781f13a9bd7fbb4024fc769271c1617b160b62821f77d6b20c09b826540204521241540181ff1156eba68f62c3807d74fb6b82a26ed573505f10bbe1afabf79d4d85accfdde58bacf25838f0fa93d87c276d72f7af912395093ae881e3be578d3dfde5675a7df316907ef4e349b8e0c493c481c7a29583b0eaa6ef46c964cc64dac3aad7c065a79ba92687ce0a98ee8cdb6361a14fce6daec621048466b4a6bbff5176467f07e6a2b69d5a59ce0127c77c05912d44efb3fa2a2d643dd0631c0c420303970e67d144185aab38122ee4d89a180002c26533406e07c05fbbfbbb148d6212908b6368226ea7c7d5b3e839910389e0099bc3354cb8d84d8a9effe2cd41ef669540fa409d96d787b622cbb530f643b09aab6a03e9b83f0a22202c68286417e48731d44a2eb367308d472ab2d860c8803db08bfa695f3f2930a8c664374b927c41dcc3c9c2fcf71e1c3efb95fd866102947e9746b2cf78aa01b14cb5db1b082a352f58fa64c4506028b405e82ed6ebd0826c6541fa085bc93ac86d87386c2042f07b045d93f017366d6c1d93ebcedd014e278d3835050677c5d46e7378734d23c51e67f1fcaebaf567698e4eda0f70e15dd2e99d51ae126ad71067d10cab934a9f0d0f88b6b004e1e1e1092b7cd460f1a170e7efb388dd92ff079c964f5f0191a51b99ba304b159294220629427c66322d192e3cb8014a8e42c965e9f09703949fda898bf106f70e3200faaae85c86e10f790ade8f2875364d93992679319355f0415beb31b498a59f932bcabf37de62a6e3e2cc8ead181b76d7f2f81c89665e5991486881ed6e85957f55d87c4de2f0bb2af449984fad5b85aa1fc465a345e5c098635d36cd5df525866c9925158c120366487c32261f99551943f7bd9b828fd0f805c91af36923afb9a1035a976cf29d7efe8355bfc2823d0d9d26252bcf99df9af15ffa66a2a57d675b8cf6494e20615cc6f195c46ac770f1fe2cbb8f966071ea08c126a5993126a291ee908a96a2214f44d6e3bab7a1f8cc9a535d86930423ab2be7b7f50ab026ae178a7464df6002c08e6f95f946dec9d918fa7c701979e5e7277efd92c2e0391bbcdfba23e102c2d4162f5812fac7806769430c50cf13d041229d170f339e9fb0765ea57b5a90afcb342c8d26ea08634abbcfae382a9292252b2722c90071257e8b6a3542a7d1b202c88abbb094b7a2f6be1d22ea647347d0f43ab767873da3d12382713ae0b132942d7950c80d15ea5a933684f30593ed3517517987dcf7b800fb8eb8dc64b07bc25686cc77bfc09b2d71f441bcff96a0a7c7bb947c6079080f694243530d600844e32e68804d47077fed9246ee42860b7d03ba6cccb59b539553e212fad1304214624e71fa2f1496d36e6ace06ace6f520af8bc12fa6907234b65d64d3a81300ed8c5074835551bc7cbbef0b6dec93fa8eac69ceb2b6fa787ed2b21cd15851840cbc48395ffe7276e88100c327fbf0d4b7ca7d9e7a4a1f17ad4e214a4fac82a7bab24a3c7a0e15438197bad66ca888729446d342811f1aa9a76c4452531e605e7fe0f6cf94dfd74cc7bec4fdcca0269fe0f2356608838073b1a2bcbb0bd130f19d0156490dc9d40165ca992696c5108931f1a0735fcb95193f56f5af1c4a70125c502bd7355b66681cb150761c244f8f1c12b1700a4aa873545c8d44f1dbd2c27884cbc54e96cd0cb82a908f5cb4f98ca4848fd7d6607c7c376fa5fbaf5b80634c59c38c194fa0c158398b64ef453fa5d1d0eecd13fb4c47d1452ed75bebf1874785457afda78924f0f4f191a26da477702053e6b4ea9a9158aeb8be5cba01eed0bea52ba039d30db1021cf35d604bafe3e53e81d7d7a2f54cdcb1a07a1de113f1b5a613d9e4b57b599353128a4e4fd25b865767590ed535d0f8b64a5ba6f1b2ccd91bb5128694deb43752b489f8ef72aa7850b83c921f56b27dcbcd801d8293d9bd61050e6ac52b47d25c4ba3eb7c3268719971b9c5f6b6285e7de73ab861c8a071a0b61d854c12f15e8bccbdb3948f41330dab8f1e1b46401fe630cd9590cbeedb644bca3ab31753ce8759476832ed9eb828375fa41106cbb8812a4ab3f2d2917d97686724f15012e3aa224edbfa79b5703723b9f1da9d8f298e7a424e717c15f97c6bf2975729f8056bec981a39d6c055d27c0b46166a6ada05e93d96d21e8b83dd54e3cb2488d3e4750dc0cc64a5a3f5ecd99eb8598c57f36b698f19105f585c424c2f0c2a8bdb04498b691ae1c26302705c2fcdbb7ac34181f65900108f4a30fa53778b73db14e6d881314fee1b43d119dc7500b68eff4b24650bb7510e8c3728a3ca4e710c32347395b4b203884db0191c4ee2039e21aed587ec1760ca67d37030c26656ebac257d53dd24515d20dd84a5ef465978759d706139a0c259dd389daef6ffa3c56f3052ba2da2a49996bd9e3ceebb79d7338319a51569811ea7cdd52331d67c99185bcad199e61682a180a6f16c021229de73dee8e9eae0e057f1a75896831b980d2376c6baa22430d90781298cd2c76a3f5a5832360d30c6d8c121ced3ea63e682940893df32891a0f20fe3771ac18e8895421c624da426b14707eea022d5814f3d774ecc970a9b1ff47bae53a335b230c2f29334f279215860b96d5c4e332dc5d521628505256bc95ffcaf7e6af856188f82b31088981c8aa702e18474e5df8f3ecac017929b8ac9a6a8f475ddd59c408014b4c8129001e5d9a9a60c8c13482d0837da1dd4b39c69b31f0d514838b6fae82c89e06c572d35b1b48563839c0992ce91307b4d837ed609baf6afb38d48e7972b8b5b99f91fdeca4c830613e7f9b72bd083efe820181fc523820f15ed63fb0822b9230c570859aab904fd73648275e5373ff1af6f61712b1c54db6d978406694e9b6038650f79671116f91705532e3dc721ae876dfb1bd00480f5eb58caac1171e79fc9652aa650cf76380bb290d6cd3732a2d080cc997d2da545fde1027339d4646c4dec09214ce863c782bd94e0a31b28b4752f7941d3a92401bfa4e37d81c61fe0f75e02162aaa21eb2c66e4dcfa0bef894309aebf66b8962fa9e8afaeafba81a283d0125ca9f4cfef741def31d6098c96fbe5bcb15fdaf3385c768f2f8cfc183ef6662a46f7b706b2bea3d914c8e070012297473589bf3e9669b9b4767073c80f7a7626f3ca968a920ce519da4e4f48f62a480065c015d4865430ca207d6582947f7403bc218272d157440faaa13a39e22f45866cad2e2dfdd09b7f7a79b1b21e0dfc0bc45b781f6950f78d4631281d285180ddc7579f12d53da5254468947f88c64d2404ca4392d6b9483901ca83f488b0eb99c6d9e61855f940e349618bb4cdda120cb9fdabf9a482fe39eabdaa2b4f8698a1085a949dc6ee0fc4da4baeb3270e7a153fc2f4912de3780b345be03f1e15bb753897c2a0c7b00b7e6a618c7b3c20e10439bcc07d2377b5dc924375ced34e7d7cc8ba6a0d1fa6697a457dc6e612bccd0964a3ac2316c29aecd74957ea9bcb5f4a70a655a1999fafbd95380d763c261813f0c6ded6f4acdb425e3047a64f187e195afb7aa9399bd775e29d3578af140b224bc801d54c95d3790079c8393ed98a7bc3e5acad2cbea47887b0163c1544a40966e04884b239de2dac9e8aeed580e5f956f8a8e1fb671e75d34e5fbf0054ad0a974b331ccbb54c8e8585d5eb41a5ce017860bb71135724903392d6b2f0017819c9ff87ff6948eba679e1bc202394505e6d368ee5be6dd25b4439c7f75a96501ee54142e584831644a3e8241064c3eed654b6207aad54cd6d499674b43450d811025dac2d3557cb347773d2bd3295ee079df0f1b3efc2fa0a9d82cd1ed20bde2bd6e34585718101ac22e513c10675f3aa2f9bac70f9f870566b54d8ce8a3efd2b60b63b6b6e16f8dd1c78424aef184ffff1a53ad572390d8edd42e12c6e5e9d01c2c362010c018763f2154e1c0a5a03fa54832572603c918595c280962a7d2c01d9259c30854eae881636f2256369627f6f380217b7aa0801cb8f5d486fff811a30fbd4048a0c81d9560ad1462dc5981aa2d8e1fa9c90f2de629b8503a127900b2fa796825e2c150ac4fd3bd7d195cb67af638e3c488b981e0312ca79e038041e241d9cf8886003759b85cd3c669ae378e8ba9422ffc09858b4f2176bd9d5b722c3f11e8c8f7cb8a3d231024e60f79258315938b9f8ab8974c1f0221e8571e00c98ddbea1a84f571064b2477455777ffd10e902a33dccf434232a62c946e557076ff7bc613e5111167319e1b3d2234b3da40a8b4d49e00b4a5d23d953bf2fce089f706c73c7b0e82c212743ece53b7c96cbd5445865fe705539dc7dd0ef0fb60fc255d83f113467e1d8eb4da93dad481732cbe0d4b4a9769deaa83b6abbfc84149e3502435b22304a721cea21100cad0220b078d0f93800b8032d73e592f88e2e3aeda6320f26cd7c4ef4299193396343c12bdbbd9a87cb52b18f2e08027716008ccf50ef396033799f9fffbe9d32766e7d9d3f4d32e6ea7ccb08cec6f2d97227954aef0752083f3ca2d5dc02994622d1e06dfdc7f043b4e947b6ce3e217b7d27b0d8db69361d9a78937e99143d81fc0990dc4dc46583f3cf73db704c2cca2927400622e6bda6427adaa4183ce35abcc598c5526a69e26a3c6dc4af36eb6c160ab48cc09ca6961d808bec4d6084741b1b2f33534553e7d24f630f0bb640c118062730001bebb4e5702ce2fa779104caaa107e1f1899fec2374a7f27764f7ede21a5e12cdb37b4ca76b6951212562a105f92a315b950d8f434ff416b1b9a1b2422542f057fe7d51597880e645ab1714fc229f68002b3d1e269ceeb32969b353e11ac49ca87ea7f88875de12309ddfe3f6cf4501522e68ecc199db40b4001867c123a1e6a293a691d8151ad766f0130fa0bd970aae5ac366b886257423afdd0761a28cd4a57083ebc02a3dabd01693859a12b9cacda074fbe5ccd2ab834b15d65093c17d5ee31d0c180f8c74b42e91330ff9a9de6c39f23c4e7533fb63f284c63304f216f7c4ae3f54a9c627b8d0c4630fa6bfdd917830ed5d3c0235a6e418692237fdcdeb42e7ed028fd7f95aca773bd7573c654e6856604ee0d9d7fa25f6cc91b0021a21d95c9e2ed43c38e92cc99d0858f791f33c7c4096b4073a50a605af92e9a31efb3fa1054ae2b053573c05cf80189cf9cb1eeaa65561a54f721df77ee2ddf01652c0435eb7597ea08e0664181b3f679113845f0e03ed829431541f05d203def0f84f22abe9fec00c6052b290ecd0db4797466aff18461037e202ee54806e756fbd0e3076fbdfc66fe4193483139f60f235dc8f5cddfe98439288a7753155bd0112d2d9810e489a5d98f38170d50ef95978af50b478fcc04ecc50779f40050c9dd0f00897baf1d4d1b06c9aac43016048cfffa660bab245fdada960e4f041af6a74318a9dfea942ab43a0f96759c9202cfac134071297e13a8d2f85ef508175c4f36719cc2a3a4d21955a3402abaf3320f83fede6a173c7414b5883a8f13d47610689ec9fc2ee58b124fa5bf5a35545d41457c16b009cd2a3eb7e109f71ebc8c881ab00c42acab3415b19b798ebc498b1c3082f4569d01e3de6a0508cf2ba3949cf042821c3acf2cb6db150a88b36f7ba6684d39fbfcda0e807dac34871ae08b9eac0b61e5a37433aced9f98b6561b794309d4baa95ded5888f022a8eb1d9f79b2d8e5956fbf4990d68c906bd82638d806a842a601783e4d4597765a60252c2c6119bd618c2ba6d69d08fd192f4a3fd2c3b4c7f010d53cd6e2a7423ad008ec05208111a54223a5273410057b8981019bf1811b991bcc366049469605b42fd28cd0b86bde221037d2b8fd45cb0c9b27e48386a963a84f61dcc58440ca032597de6c3507f1e648311c5525fd00378d3432955cfdf7eb87fd3832624d912a2696d383a5f0090b5ae652a07570818d0455a505c3655c003e79ed841cd1a02119556b5f142928ab98a491ca0b486300c0e126bf9308797faf4d6d4f096c8fed301fa9aff821908059e36c2a2ff6e783796e33140ff21e46a3e19320a162c0a80b574fa11c5610721789046457a8e122dbbc31f9db8e9d60eea6fdb78fb62e002942999bb7ee575ebf42514a77595e1177199575464f7cc47e535f0d0c564a3a1b2e5e37b1d9f7eb0404df692657f7d4d5aa7ac1418d3bb1c0055afda07e6b1e1b6bc8f49f0e6255250aec766ba36d26c78a34c64c379689c4bc13302fc0a2e90923bf1e1915ed0ca385aba72da2f48566569f21a88069fa4600df845309ef7b137e09f44bc8215c0b31d1191797b2a789fcdc460bdce0b58eef3ec23e7f46ee09257488dd2f164e17a31fed823468e23e7791d0897daf3f937ffe7d05bb55511e1c417c6f2fb6fceea5ebfcd854a23ab5ca8fdc7c04908d8b81e436207dbb1f18da479741bd2883269c262a870a23bfc99ca1a714ddcdb769d695aa747bf726173a91cf40d052149374a8809cb89c2ccc1751c07e2b2bc4e286774bbfe4b1712d38e2106b4546a9af90a3008d709994d0adaee76450273eb6715ccb2ed12824070533ab886efef8291c861e327d1198221667f380dd075a86fcd21d5f7c3ff7032d213496e23fc2845413df185d31f73a6198904c94ddccb0fefa0f250b599b0223370e91052e2b4b71b6133793f6f6c9a5f313efb18f2e88001e561b480c7f128af589420a68ab0dabbf4118cad6fe88586d6759c1395cb199cf6590a1d4fd052eb2aab72f8746d2147262fc3c1a64235a45ae1d171c31a917208adc36b84013fe1e6b33fdad0187aaee03b96a3626e4d5006bb0ffcc91d1d57239ce89461e0570641c01456e1c92e19a0054d9c812de26ed8cefee8f1e29903867aca772a11cabe48a842659044e170f37774282a95dca132c110aacc8354be42019156dd92a790c670bcf81ab066867a237e984e6e51b28f0b9be32323a1b76eef7d25c4d0e2079053cbc8ba35f2b1823b437a526f482d892c240f8e8258eb73f29d77f700fa00cfa645e659a661969d96c5d93a03239997e24f2a3d551f74804e235bbc12117b470959358f27fc14086c9d9494b8f6074e98cf99ba4d98607f8054e01c30dd270176d233a81f079282ac2d90d61e6278c0bc08fbff1914b49e432e0039b2b9d3af036e3554540363571f6cf94384af6a31647e2416da794a816dcca9e930ddff997ba2d5d6ca43b8b27ce0e5ef64097365087bba89d904ed998f250f93f134d50ffec261e5d928b0e7ea27594f54febe371db232923a7dd799d8de591cf005909f50abfb4f11d0af2edb4899ca7bd57cf2ab1b8172af3d1cdb4b32072121ba1274c502ba63577953f92f9dd4f715fa87411d6501435ef42d64c3b9941c11c5104477a3a7c216138f889ebe0cbe7ad8687c9cc998c83a0a5d64cd37b08a80411ea0f65a76c75969c095f9103dc1d950454549f95eb2b4139617dcb0c7d9e21ff3f9786b19ff2456a4c77191118917a82179807d42e4b6a03ea7ccc6ce3462f124adb34301fe90c49423e41e8a0f135b76d6653a107f8f91c9d8a3fe14874283fd2c7d4173367a0a729b8c378f396ee73c3310dd807b80a12c3e1f50e76bc235179e6eade026a5b94aeee06760fe269c187c0ca04cd22f8a6933f617ef55221d07bbd98ac54cd8d7e4b63980dadb35296060af0bab5cc9969a7042cf6c8b0000ddd081697143999fb6c1e12bc4134602fdae6180e5a69a1b54d203a0e086b272e29940a796957ac570af02ccaf8e1cbd94013607d2f7bd4be7c466986d14d15b90f5f649d3da06cf9a2d20d684075971fc6589466ec9560f78f95d63af4500e621998656153ca8ba44402b31b19cf7eb932adafb783547e2e019e152fe3361b7e76c63017866dd5eeee8c7ee7c569a1dee58a78b8c3ccb250600c9aab1cd706a210f1d7c892ccf6b68f6dc42c86f8993a9634952c4c9cc3ee0184a64a28a60afcd2605a76a47a34885bf7cb398e70dfba201aff2221f55345464ec01bb36a2ca81d2a0e0e09280964d5c06671235fb5d3976aa2c31f8bc74c0e3f6f9fba500e7650be7a2791e8f7bc78c1033f6e3e829af8f5664e7703f0b48ad9d3e1de8a15f7812ec86a5d13fd88077241559c19a4cc7c174741c6f091405081a809562b1d7b74b4b4c7fe9d36b5d542c28135a6072ffc5ca0d746fb98588ad7d35df9e618b80609be85aec7266ff9bcca42c3714c9f9f2724fef38f698e63d3139c29a6", + "public_inputs_hex": "0x1d420eaa08a65528f470fd3e2a802913b611527f41fca008a0ad4e97475078032a555ccad424037773cae7569cd26f46467d9bd96c32334af741c911096761830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022197e95de61c6c2844727c848aa819fe89bff180954ba01135f7e3d285aa3d8e240e1f1fe5145cc75fe7b253dd853cded77fb484b8be9d52aaf0a49098afcc7d24e0b65d370477cc168e835d8143177b582294e4a47357f372f960754b56b54f2a318f2fc85748ea90c49625631654288c77791d8dd0792e201c748ca9863ac417b852c2d0067302ffa20e6f7068292fa3304e6e20e60a0c51ed55a2e0c2a2a615de98a2794725029dd283936e25dbbb2d8cf00dc4401eac6e834b094e5efd8e2bad40c7a2fc975f2e4811607e4d5fb72361dd1af1bb2364be799270aab5c6f623db21355d312ad82ff6334e39518d7aec226005c56d124daf506a44749cf370" + }, + "decryption_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000d6343409c0afb816a000000000000000000000000000000000000000000000000e0e3142188542d9d000000000000000000000000000000000000000000000004bdda217c121af9d500000000000000000000000000000000000000000000000000014a5db1afe856000000000000000000000000000000000000000000000000ee178f82f74d1cab000000000000000000000000000000000000000000000002e8d0a46d30478dfe00000000000000000000000000000000000000000000000207560c01e3450dbc00000000000000000000000000000000000000000000000000022788c7db5ddc0000000000000000000000000000000000000000000000099ba154d1691f0c0c0000000000000000000000000000000000000000000000077a57fa84b59575440000000000000000000000000000000000000000000000052b18c02725e6860800000000000000000000000000000000000000000000000000017e9657c0fc1c000000000000000000000000000000000000000000000002b224b4548754d742000000000000000000000000000000000000000000000009134fbdf2459e11e8000000000000000000000000000000000000000000000007ae759187042674660000000000000000000000000000000000000000000000000001b7072ac05fcc10fd82a9f5e13726dda894346515567a79c225b241a718f1b252ee23cfcb8dfc134749cb199d7dfa121b0233c0bca54919eea35871367be619fab7d4acde565f21f7d05e4d6075633ee1781849710d0cc9f901e277b8147885e33549518fe8c9235394cb328d148824ef86c283f67c33bd9d74125ce290de790d17252755f12a2c575b654f3c0128b45fc00733497bedb1ab89208d38b1062fbdcd9874d1a1102203a3af11c6d2beeefa926f37841cf1766ee9c1fd8fb937fd7ca88bcf091a3b0d693f463de1bc4d89d66c527f61a537f8c5e09d43384776febd12c1a0b160192419f01ad42306732827a9e2b737e59e99429dafabbc4b63fd1eac9ac2d8f50324e028c3bfc9cb7efabedc43d2c85fd8454cb2ac6edb769ec5aaa71a6813ed252ea7767466292e673a4791482b20189da899063637b2fb233fe7413ebe14ab48172ebbec7b1577ece1ca982dfe9bc31189268e16381b3452830ad955c85334f723b7cd29f8459a2bdce9108984d2445710388a4ec18f02e22446ef9281b115a80a16fb591cb108f0398b7bdd4b096354d07245988cde80562a2e3997dc8d77ac05bada7a25ab6675abb5c42348a44a313a519ade461c43aa3993e73cfc06472e252e3d75992b831f25d123331077a32c38e1377c7e7e41f360cc4f9cb84e70fc047c37bac2870a10065df9c6c9405302c93374fecd0753fc9874bb9889e7e2d8056c734dfc773c2d255b48cb1ba153afd8e628b1a7fcb0ca36233ed95a92e6960811d86a8a694956d28b0187c66038d4aaccb51e0a164bd42d83fc40fb48b8a61af5e281d9149910f3494c80f943107661e722113d7b9a6c0c1deab0beae72c60ec45189b66a1679eca9165ebc7a629d2e71e0a594277d0fbbb1379fa345c9a61c5b614ff22f7abbde64cb1c7c49431e04559ba35828a18bfdba63c1169090a409a9f16759479cadbd816a6eb1116a9a4d0c3ad1b5f36f304a97c7e87643778f0c38118f46b63bbd48cf9b4e18bd76663b71ad6b8312ad607a4664b2f47259ed009c81da4d44d2d89b736a3ca86649ec926b8d9f5ce807ea302b1ecbc0349ba0010534881c9a4b14b496d7dd5146e97bff9978f74eb7cd73dfdde685be41267606e74867136658c65220b3f1515fad8fc3d291f636b9ba4a03f4e288464e246a17c606205cb08af4feda633d7e7358b8a8c1e3a9bb7cc3e0089717bdc29914ea0b923cfac7c47dc0b8d04a4ee9071fc9317c266eec4ccab59ffae46a9cee283d05e0a63d50303298db10d4af510792f740a8bbd35be7057bf1cee727e79394c22a8e2545755f8a0599a1e150671f54850bfbd1743210499c84c3b77b4d1f66431069cb273078a2e10f1f015ccc54118eae036e1947b49f63342d2e5cc69ac3db0e6346f2648d7fec2da28cbec5afb3314ceda07cc2c3ef10078c086658fdb63229c49d8545542435bd4d3b1696c001df587e38707a12cf521214825cac7af47d227e93ed63f59ed33ce031cd61931a57bf28f14f457a815be7267cc3c210ed870dcb1324eecc54a3357207d5d9d2c42815d5e7b2a65b4c9d5f1e208a9ed0a6b4235e122935a8843159470d69ebec0a3383369dee35693d475148f18247247c071a06a44e4197aa7a02bc80ff31e3209552172b66163935d82fd56dc4a6a730ff173fc70ce51c6c9dd197840a1e873489010c6750c0f7c05ba0de148c871f50570359ebea3159661fd9333c2db2b4f5041249f8dd96ad6ecd2623078086bdb0e51b67b47a31148be3689e5bc49025c1182f1ea881ed3c65e72c2944f0928668171ec2d7741c74f5047a6b13a71eb54058979c872ce634aa6b5dc6e060dcc85d1002cd3cbd4ab0b1076ff2360427b4157bf24c8d965d6c836962a84ec8315cc713080b314982a7345e5a38ed87768e95095ab5b39c8736cef5710baa273277ac2e17f55debdc276dc29eb726c7a938b352124bbfb0a07c26605f144d404bbd2bdf149594defc22c1a6717c5147d2f36dd017d5524107ce84c6e97b7a143e29d52f25022de025b573b9eb662e6c3d09660e4d0b423a16661e9cf66f44eaf21945692150a6292c541bb691e59f8ff4fb579f797bc5d89b3138d8a7aeccedb49729c724beb14ae3f33d99876f08496a48a22de7c436ec88364ba02e10bf3c52236ea913e8426d7cc3e2d38c861f8981014f91432d53089ac70e114b86d4a60d150e51107bdebe9f1e40b98059a4313e5bff2e5b3200c6ca3a0545a8f115bde4fb7d7107b2010c1aa5c9d5ae36db4f703cce98712fac6a633da3874a71943809c40cd7260a628aede79ffe3799bbe5d49288b947d1d067f4ba336f26bd7862510ffb4328331991a2f89b9f53a3620b32bc7bb50f76eb9cde2cb2f9cf42c4a22df0c0e20331793e2f642f142bae542cb7e2f0fd200db0b710d3fd3c0f4d37afa38b8d501fc34640655f2776937aefd2c0c15fa5dc91fa5de878ed805b700436d8ea62ec2061cc0c19517812cd43acb92e01018dd857565ff19d40bb8f09a5f2753b26900f1ee465a4bded176bdb8c4cd3589184c8c80c0b95cfa3484ae2655c46508c4b1e06aa30e32f43f454846e4dfea668903fed3bf23762dabf7b4d7fdc33590fa3010b8aa4bdf244b628b32e4468ad96056a848209a65f1c42dca8318754332aa109bbfe7a82cd199fc831c48b5439c09209b31247b258bb665d2190407ba46dad014ed3c854628e09e8ba9da2c4e2b1e658a6b56fc772a101531810ba1efd61040ede249e8bbacc5b7f064e3a0a89f98d64bccfa1d47c52bafc19f615c4df0fcd059b763205544ba63668706829151458142db92203b996a171fdbd9dc8016f54105b72228df5503f7a4484b4e99320c03d7d8d384e83ad9cf5b9ab322a9f81582f48298a3a781a02a0fb4e6a7b116dc94f11cd919b909ae8fef369dd4a7498252a0c3cbf87c8e91ac7e56d9bcf6ddfec337df1e6f2caff2fd04489a0e15f51c00c8bab2bf1e204b2516dde8c6212fbc5d519398e1d7ffb0d3ced8ccad27638a0183755e45c97ed7e8496714a425b0683362ef4cefaa0acb128464c50054393010a3916f001a49abadfaa9c44052829ab1373491eb5afc19c448cc2ec2384cff003b6ef542acbc10237a0355395a4828bf9c356e66a92f998a9860477393e2ecc09d9a7501d79a694699ccd39b0fc5f7518b6ef187bea3938e24ac1e649107ae7134b4819e221010ff3ea8ca2aae7cfd8c913d727339e5e90d8bf9af431f2767f229d00d4bc9a9ab2708b1a268395b66e88603b50f8ec614b1ee8f042247191be099258078233ddbe8699093187d4b87238b8503be1b3a992a66efeb3c15bf46e114045770bc9dea0af8d1b3b9e7f89ad0f0f7b5cb58347f9bc31a1f5b749125503095d5ea015e6af870476964d02d0836687d9e205ff986efa3fa05eaf42567813be91e7d92751fe7dddce9055502b2beab3e4e3b9987491834fe202b41a16142628026d775db7141e97e2d4144abfd41e23c68dac14669bde63aafd40d4a8002c28aa160a0b5b1f57bcf17e056e62e9a6a792e75c194faecf8edf72ab65904b061cfd14a239bc808454c33b080a44af18784da9335cf5d3de85828c5b2a91d113bf19bc7ab5f87b921f7b88712ef3895fbee836d87dd311efc22d394dcb758321c9d1a26147d519764b79da0bc929d245fed23e95e58281d43dc93a611641ad104e9bb58a706ac4f9212e22869a7d7d816c3afc5f2b9275babbc2353dc59c332db15dde7753b62322c8bcf8d41b72e3bbe6ff0a2c61eb466e5512bf1a8be499301fe18941e16b2122f0fc390e191cf3a4532c849b39956f3e318c907163810611034a1a296a7bbe66780ca88c6f599ca09c82d83d70e1bfa4473776b5c068221194dc907822535370338f889825f36a24db7a3b42168201e5e80264e41e7569162cb3669ee45cf5c0810dda88651c91cc32fb2aae51c18f55174129409892050248d04cd731434d63434389f80310114dc92993c9b39e42550954633cf31d241754f6dc46a21f7be676f914feecb63bcfa9d839638e8fd140acbbe7e494540a1da5b4f31a302ecde922b1a10aff437aa96759c3059fa958a3a6e2c50361306d1c4a7b7f63a4abe9b13738ccde8195d2cc4fb4c3c85ad53c78dc8496283d0cc601396dd75bfacebad9ded60880f37b46bc61c87724c7b8c0513f1783675e4d5018f7f30a9115e2b95cbb5052e03b3111d90798ce5272e2c6228c165fce6c347c27711e7de6d91d0b6bdf34677334c6e8ca47a60e0b7bbb5a0f01a6724174d0cf0f38bdebf434e84d92160285043af5227e5f628012786f658f53dca24e3d3cda0841e6a5b1c9be5b9b898e5e71a0eac8825cf7d8b4f38fb0138dfda4cb5a9e5b0cc2d6ad4868dfa422efff32fb32a6535891e60413f524f001d727d786f2970e04e0809642af932031d727274d05962dab59cf469ab5d400f6291950cf78382218b051a65adfd64e4e81a5e31bc3dc22dfe95a810750fbfb0e9bb9e230aec7a3227e15527102ce7d9462df9e992926f691c129f6e38371aa044411006660b45b22ed9c9c0335ccaa9a3771614eda0ee18a5b1293cb713f3e4cf32209bf2b2be91b52a3e0461b00b50bc24212e7a0a168cd4a5670eed7735141ffbb2530bb11151d70bfc2ddd7bf86ec678546a0ba985b6152c5b427e31c612f298280263c0f312db2b751667a6b85ba0fac6656417340203010f463292039979dfe7bc30897160e633531a0d52f9a326a3aee24c35fbccdaa387a801db8f6d9ca2cf6b6641eae06aac300aea7c12bf9a28f3b667beb873af6f9caceec3fc3f0616dc7f4bd22f4146614c7ed9acb39a3915b92ac5b7787a877f46033e414b721b49d8d27e5ab892415cd864a75ef2e316f4ba10efa47a4559fcaa336afc1d9414c0204b98cc0a70626f89136564bfec778ef9807939900337c2616739d4a50f3be2c71830968412b0790e7e1110b375a19e3f5ffc7b3a605e187f41bff4a6283828996fd3f26a213a28f6e3ad328976ed2b72d62ad54cf51d8215f993325d697137dc2a4c1e3c80f6462158846588d3f5b8cfdafa9b1018b7b1348b150b76bcdd0640f57fd2d862dda4449740d5cb065e00bc50146bc70b3dac6a6e9103d0863af505eaab860361ed7accae9e15089da9d1d801ae35817a5f67a28a604771cbf3be04ebc9c20e51368750ba4cdee1f00fa042d805ab474446a90cfbf3fc97a20fe1ca5e4a6d588266864684004140b5150b5cdca08014cec724f1aef668d2ba67254a53f2c59d50ea76d17c1e2160bcab9fa7540b366abfaf5f8413244eaf950547f7571cc057729ea749b5fbf56ab428aab3ed476cd4f68b3f41eac270bd6b29fcda4f75626071b1a20be49701c43b4b16437ccc9fdf48a62fe1a2663a68c352e147f4ae8844c2807157c23509fbd64ac8ef2db22655f9745461382cf08b2d3cfdbf28081198a21ed719565dc566fb084e14c45856676c2a3a981576fad4bad652a20e85092a128f13027717bcd2bfaade88737b4ace18b183076e1876c817935ef5d7ba8b0622f6b2441c65d5d4c293d3a0506639a43c5d085c2df2b838a27263902349be4951f7f12272801748a9b3d4245de5e60f77cbeb1454b069a9f476e59bf36245722244ac46a6da45d3406581f44125c5661200e0d92ebdaaa3d14e973d2618ffc9b2081a5ce7bd73efba7488ec506c08e8100329c8a9f4db5d1d94165c5e0a21f202a8aee42247f7d031bffb09f2d852246350848d82a5c139169e8c8d39e6178bb264a9dd76aea3c0ee71750c7a9287741eeca96cc3e2418426d0e24d5665a4dc22cf017f7fec4b71e1e288e9efff6882b3fe1b39b4a527403b8d87a77b1f7b92511ef72f0386ad6da5c92005b739f5bb3c6aa212453e8e6d343ade9cc24a752631e63d16b0a0d0f0013302d8a6b592cac45f107cbd67975e6c4bccbb48572b6290fdbf02aee0467e7e24d7274351a3fd001627678697c6d18fb80fcc5cdb2b79e294219cb7224ebc6a5ae6ec05376afda73fd323e700aea6553a139f1bfaef34111e8014ae15ce5ddc2568eac8f8621f643468697c0f957c13d13de82457e4310297c09ac3934c2a272a10621472fe0deb9eb13dad684b66f5b19a420d8c010a82fc2de64ae10f7ed94fe5a610ae0f8889fe1d94f92544858c65ec64b95055ac11c4652efe064f85ac337332ad95955bb6db02f2d11040cffb5d6a8f9e632a93b14045aabcba545e42a03bbdb72421e4e08644e587725d0bf29d3c8a235bab183158dc24705ff40a5f24f8a0ea39f30aef722faf69af92a500abef9e2f26a2b642d76adb78616af6e74608fd27de1c8ce87a090d832f57e13ec2534abf164ba0b2be6d35cbaefe0366ab88d79d0f152a4cbff4a40a4dd1585cd47f7c6d39492721b4819f391ffe75d71858e5e7f3b7040d6d363761eb4b596aedbba067d8c4add0183eb7e4c92d2f449f9287ff1c0a8062ca1d719ef98e276c98ed954559047ec1aac319dd0d0e925fd34e61f3b450c6dc69cd7f50d4df31733d0652aef9d20d91b5aa21fe2b9a3c6915f614a7f1616959cc3fc32c5187f0dd24b0f51b32272ea072d7e084d62c3324dabd4f1985dc2c0aa88915960a5c1785ca8683207dbe4792d9d900add917b458ae42c0c8f66b9c414c484644e56fb083a7731d336d210060d5bf4c1b5f807c4692ca713632bd87b26ead2b7182937890b091a15f42d6ca2011026280c64f222ffd8629a17136b4c7a6fada3e2742fe377434073a9cee2bb03246938701a602957d1bb0abfd402035df562b6ac784c99647ac645c7958366136f0024347b1fd8bf330b4d697b97838393c0c91b82582343eb58e2f9d6b9c82b1387eed1f819c4d9a45a7e4d1ec5f2d2f0a8fe5aa96705c2058e1f62b5b2d5254c98a089c8f5eab8617604beb94022770aa9c76fab0cca170d5fdc2dbd40e628da831293d1c24273d9523a420bc585f93d4baa497e68f258121f9647fb2ef90bbad294f96003a9069d13d95465fbfb65362e6c70e61b6056e5b7053477fa0b17f609298e716d5fe9e20b2e49d5779a225f535ffa20c88bdc387a1ea66864d62571705f8745c3d21e0b714826d23644b10d5f3c166f1bd704291c20e7f685e8245e007dd62da8e45374824a7d819c48aeae8cc9beb2988bd8cb3cf074c7af0f2ec4fde771894a79f484ddee1e2af510dc80843c64f2dd12b7fb36d69a4b323b1d0aa5f93a2ea384df044c2132470d4c5aefe263fcdf47e68e9d26e63c81dcd32a389e21e2d56d771c823017fe31533809c3b5d3016afd6f95329ed4db23daf0106cd2e9f2addd7e0f013c1a32c3d5eaff36d796800acb744179cbd788a15a3c037261f29e401178fecd97f8fa01daf54700ce5982b1d58e025ed6ecbd300e7107afb7af7e7ebb538d40acad316ad54db0bab5ada811e395e0ebe6cf74ad149629c2fd131d0ef7d2faa4fbb177351dd1e68135f5ad97bfd6651a2c98ca8ef85926aef7180b5d563c5ad7df270d921a79feafa12e533cd9b8d602fea0ae16899729fc9de73eda204ba93c5c60ec0420cc4bc9d06b189045d9c12c71bd79e673c40c7ccd521d3ff61c7eceb8e965c00de62c8a32acfd1f121c0ee841fa2f756f0618f2d4d6ac96d7bd74f67427e347e2e760446958f9115ad9a35b530e801071be246e5576bd91e99ade8d75b12fbd1a43dd83960b318f970045dd374984b535e72bd2ba51ecd03b9396ad32e9fc4a8fcc22b203b32a45263a795786f4fbdc459b0659c4f1cc8261dfa55ea5ab693197366697b6ade5d4340c8192fceead82ace629a7472f3b13c28a954d467990509f4ce8ca0d37464673ad92a13c2715b7db55250d67b3a7e4d9a735099f8aee1544d0e6fd73f0cfad9c3aa5e40b0e2b8962561ec35f1ad2b11aff259d79d1baaba2fba96eb834e76a9c80b364e97b24307a281424aa2fa30be62314f75d116f5c131ec32bbd3d548ac60e287531ee45b88a9911e2292468a9077985e7f9bf3b9d7c9c7f4f4d58a034168a0846edc8fd6e821919bc426b90b9d31fd35ea2b87b4ae485c0684ab37528cb0f6319003a27dcf72e1bc9e5dc54f4a62cae86cedff569653518ce21fdcc660bbd5e7be989b268663728da72800734456991bb11783aa00a75d9d3e930bc9355f763b4c3d040e1dcf01955668b29288a41828a44bfcce4f3d3d409fd71f61b6a69b12757debf0d01692551a363188bca817da75832de2a3115a69e2cb747b0cb16ae52e6ee572c5de717941f01982ec1c364c7cd5d4d6eff0e3b03c68e7dca325c1e804b2e0abfbfeb1c9c593a923554ecd202ce87adc8dd2f5c4866d494f148edbbd7496abe6faf5023d53378720ce63e06078b8d9e84ca9a1d2a65616bd2def3a8bef72908acca0a10543ea597c8d6d636236f8faaea56d55a20c9142f080147a46a88648bd9dc11017aa88cf3adb1e5c174be8ce4b43d33da7b54a2d92514e12b6b768ec63bf0c31f2a9605389352931a3b69a1f26ac4c2163544780d60fcc85795256c6afa280027b06fcce4b557599d94a87b5c481d9a34c331c396df9656fa89ba922dae138408bffe3ac2706d43bd7fb1c8e56f3718bc24cd0b9e9b0ebe94080cb5eecce6480f8c185f442142926ca3172b2e19c03c0722752911cc8a6c7206f3c2912787122662900584b849d650e0c4eedfaf8187238a97f307266eed20d6e0b6ba01b9f20046fd636ffc52fc2d5daf18ebb043f41bfece62514c98854a64ebc2fdfeaf7c1cec169dd44365b740df2819d9ad1aadd76bdf6033173f06ac4d778fa9d4855822dba8778bcec03e6fe23987933ac5841cbc60c642f2aa3f59f1eca01f7802481358b76b89c085167d1b82e5e893efb5c368bdabf60c4d65c8b526e791bc70fe24da05333484e79a43adf9468afc8a513e75578bc37681732417d87d3d1a1e5a1d7680fc28c20793b079d2fbf91f06483f9faf0d3ed1f7e0c3414ca35b2f25e7277eda67942f851dff283b7a1776dff8760a130b2e4a95fa7a494e866404815d1f8313141a02a6fd2aaf2204dbf452587087026b47df4bde2c459632697f3909173803e820b6a810ead209db8c49720978493b40daa7651c88244627d27ae18420957e21543565fbd8367917180042e123042789206e7a0f382f05630a7233ce23870618eb29d57048ea6baa35a13e7775ea499b77fa2b2939a21948c33c49b80eb128ad72c44ec6b2c43ebc0ebed56c4d357759a372cb724cded062b46bd9a7242e8783d21021596916098b8ba9210ef0df0b8f5065757dfd22b3564c2cf1c62776f8659e98c20f45088864e86e85b8e61803d2e2e8db08c5597633e2884b1312f78654b323134010efe0a5a22f96ff83ab4e467746b698b8d2d68d2937d3132e98b53f62eb12c772cf6b86924ea8990b7fe9f6ca76e36ec6bb71334d5fe7ac0ff44d2a4c39e0447d41ee9144c125ae86e1696d83894163c929b99d5657682c0ccc8739c3c024b7d3b35be279dec63ccbd81e8c0d6e63debbcea29386640dd127985d1724b1ef912fa749d00325fd280af6eef3c77346dd5e2022dd02963caf2169bc8168aa63972cd3c404977532baec258ca30873d54b585b7de7de78081313ad920afd58a88ed6de63c31e93a3c05693b27665cfb4daddccb2d584b0c71f0577d99ae959e0d3295f3b009a1bc1b357cdbd35bd564a90c10c57a52c4d5c9e175b5bf6cda85e75a362d53be71619e033f18a912ac2bb171a8650b6494f385c23cfb56b3e56656966c1c3ad6aa4ff5fe93108e3aa5f266feb88c3654015fee429eeee7128c5e0b683bf8670ef76f2064c82e33acfa4b98fb010516c9758c24c08287df25152362f76b084441cecf158a6a03c74473f7ded3f9a280283f3a94306a6b182ca1c741819fa8676d33f15534ac596a39d184f208664084e86f69f491355d22dec6c7fdd47db8991f40363b46b90b495a01bb12e79bdfc17c015222c072641d13506921a872ac44c9cc8d108225e2aaf54c7d51d7a2b05ef429931aa01430a19e1d3fff8f96d9abb6c0e0cb3f645c059329e2c08162c99890102ba0d05634e00f98c8be1b71cb16bb2844c4cdcd67eea6259c5a9d668c058afd5889e27f0261c1586d2b4cbc5948a248e38240aaf1b6ee10801c93b9f6bc130cb04460efbe72cb208793fce34c92d5cf696958d7d560e5ff6847c635498a769eae2392b0e3ef9384f3ed5a8fc649537d71b6c540bcdbc695313c2d581d999edcbb7992ee1be226490863613c815b8677279673ed4659589212807f82da56e940e674601240ccf06909e2191a4d52f09a513a0acd557e70ee7bb5df0179cd2659547b10fa1792b0ccca44cd07e4b82df1a2c5e017d2f8a32c0842937f182a9f354a63516308aae017cf8a00e316b678fd379054cacb79841e0801c32e8d34e5b52ea8b0c8cd36caf58534592739dbb0ab2de7572923ec1622a98428768e440b38d4ace26bfbe8863b8dca57239ebb222338467db5400732d172f716e449e63c92fadb419e5644af6620b3258e48e198f2ef956a6856143b35a756ac2e35cfcb6eecc7d178c6515c496180fef749ac8e977fa63a28fe6dcfbc73ddb360ed5709fc9b0fe026c4635a79e7f4caefe5299dd7cf4b0210925079bae38b94a1cfd393c36b5730d3b39ddecf9213ed09c1760211d7c8299f793f875acc0e8a1e444a7c8009d5d0df95cf94b07d8ddea9e064bb63e544b266a94c00d0c91b75697c7164fea0f912983f360a60797fda997f5f370162ef1847ae23ebfff5e72a8e8c719631b7f8e24c08cedaad805e39e5373db066ee5705cf40a4641472965ec2e8165fea29ab119fb1fb534d5183820622a1d4500fceb3ae14eac2b420e084526dab4088f174c03abd7cdf5e33ecbcb6c6b1f09875a347c283cb0920de180cb615648c29c203f0ecd1b1a3b9d78569171956034619df0c3f6bce2442e302b4a7a0d6c321313491247bf62042d00eeb61610243fc11ad0d517806fb5f9ae448e7facf517db96571a6a1af751ac14a6383f96870460481013a08d296259a69405f1b94b9c50af4e262e4a32bde88f8a1c7abf78808893ed9a0b293eece0feb9e5fb3c86cd4f874b0a8851b7ec202d182ce02749dba88d816f94c2304cda0c56573114472ae4789903a9782552283c2c2b88ed75ae3a610b32844cbe7e7f7c74f5216fb6cb6615cc2797978cef7d47016bee6da4c77e9f60453cc17e44724812dc958172c38e98ba2407ea8b08e0f194575cee3effe062c4926bce85ba7e338a9a3fce58d4e021650d19a35f54d83ecaef10cbe01579973ff5bb6c07b29feb89ee137864ad11a2a70cb411e2a5b220b3fe8a74bb8d9bc4b624dc5914e52b9ace98e7671e0cf5e92b19536b803836dde90b9e384ffa4d590e141d96cd7944b79c6fb3d80992fc108702956f27608a987c9947ce3fdd637773787e0f976bee528e7ff57a7fb94fb361268bd81710fe3a615437e23e557ea5c485b4a6dbcd89e24eae87ebb9ae61eace002385c62bc8c9c1925ad79428be87cbc883c29c2bd9bfca108086de9053dd5a27999b28a3b0a8e41cf1fe430c3a035940be16521438e35fe5bbd212b8d0bcfb0135f7b015e51ad8ec8fa8df12cd077ad2bcf7a705889b9aa6674aa84c0428eb1ce7c1fa8d1b1adec22d51cc8a501c42b95c783dc1320c9b4d0fcb6f5dd4506b206f292e5d06fa78f52666675fde9819ce5dba63fa92ea8a6463422461f58e622d8937aae3718f509e1cecb3c95c9c82ae33ad610f692d7df28bffb8ffd4b3e4039e63003aa372590c543591e7d89ccbae71b74aa468a70da3db0e3ca463b15f0e6f4cdeb5bbf5ec3d736f1505610aff03ab11756a701f5b77578daf8989bc322dd5c44335a39dae704ad3f23389a598b98b69642f6cd7fa1830b998d64dc6a3250d7e6609e26e1725a4f6255ffe0e73e002b4aad16a1ab58b3fdcb8a26958830810ead864d8a658780beb619fab6c34e15199c1197968c99b38a5bf174478d413830e0056c5c2f967af9b3d26fb050519d4800bfaec15e7f13a94dcf2c5a2bd1c524d5ae0d73b30261003402d404f8e596ef73e98c0c4a6acb82456870f58671d138fdfb25ca284ec0793739a7cee577e6d3ba319efff2cf9f22b90f604e4f7014c701b5b3651d06ef3f3c3d566842801f26b1a8cffa425ec7aeffe6c1205932807754ec92ab14d58fff617ef19940a7e40c95ba9414628d59e6ea2fa9cc1140dd37f315857802b79f5d1b31c3b076de22ae95fdbbf2850886a0c671a67666a0b789aaeb6190fea5776179f028c774445d9c61c76dfe1a263c30a0ce5880bbf04378426e45dced169fdf580d0927fe256cc195db8122edb0732eed159a32cc72cd17f0ff0775670ed47492ab73e9bdb1646d1ddf6fac59a2f1698dbc00da9fa24dc2ab6ee98dcbd0682385e98342ffc86fc964c46b89ccbc2e990c68a761169037021867fd84d7db8c3a74c2a31bea5676045a5d33c4f525d51c11e01f58d200f0fa35b54f19c81087074ca714fed679d10f181f9cc2dfdc8cb1ebd703ac7200150fdd527067f0bc99b5b785afcb640874b3f62159de99771e6a86310818e5f2fb0169c55188588154761e71ffe774e208c335942d4dbe4aadf295d59297039066fe4bd1064d8ad040ada4cbf1f5cbe7b80e29396dccc2e0c93e4c1e0f373db107e57b560504f1e1bafce78380cd492758e1616d3076b68ada6dd12ed8adbdd14e14ff30a2ac375956f6087d8a68b13539c5a45d2b3de89d08a7db022f688050ff38bc3ad29e40c07a6159f119da20b870054811250aeb41f835d074b948a6b0f6f2f89422d726d91317c14441ccda2e382d0cf289c03d98aff6b3d34934bee232323cdc38dbb69f1c9092ada5e3a9cf8aa6e130203f1dadcac0ab7066a3de015dec2ab95501c4ce019c7cf444beb5d20d0e31b74e319c170c52acc6feae34009bdff8a7a5e189aba127f8d488ecec7bfee67c0e4da40da08e1d216c95e4e531569adc78433ec670379654df38bd2ba311657bd0273f3f945c45f7c9883e9042040c5b6cf63fb1069b8e0046174d371d03eb6cdd9029575e42b419a8b72380122ed3efddc9233f58b6c2dbc2a694d2b79011a794943f1a99e6603632ec4085927adb6976fb676e768d1ddb26b2c88158e8cba7b666ab6a20b030432ca67c8eb29c3b535066e0f779fef60ecba39001047452fe610643fb4491c13b86dbef2f409b504bb782009166f4d3069566271c6cc026ef64cee56c321be4aef2e665d47030a7fcc5527f2235722880893ad58c7dcc873095fa719bfbd937803dcc2788302a5ff8a658c1426defc4915c2e49e49ac66eb4e661d97eb9bc1c19d03228a58003a38e29ad1f40ecef9edefa3c9d86d6fa481d8bcdffdf1de0e419883f488bf2684050e1b465beca794930b7de04f78f0001bb18b954352807a99200f935f08133200c22324dff58e9f920bb0e54c8781c29ff6466cd26ada6ce05255248138001cd0f79242fd0768675144caacff113ce2d470a5d98f9ea44b6fd446e8511c1bd7c61a3d26af3415eb3532dc9b7b243b34752c63ba0bc2e81bd6000af3ee3e2f9409ffd485289bfb3e1ff44d8b181e081f9f948aac37c0d7d535cbef1a42501a0050b1ace19cc1779e23acc5aee850bdca8fd5591bbaa08e5b94d30df3f6b32a05139aad16899b7620a46d0be03c740e38704090e4d3d584aec4eb2d56f39a1573706fe29dae924284cffb950843d5e3090b3b59c9ea76a1a2215bbcd869712c7129bccf788ff4ccf5d9f28673b69788488553de67c648560a49f98c9054a30968dd170b7f9ccdc98147a7b6b0552bad5bb39a2eea0dfd942b320ddcac5e382ee141dd1b89eb46cb5e9da7537f63b77523abab01e9574ad161a911a896b867123735ad4c98de40f373bfd62165b0c737953c8c816c27142cd245917969bce31163936dd6680031e303c4086e9c8a6de7195c51fcdafaa9626f4691f201eb851e943c2dcf5a5e90005783bba67b6478fd637e43b5dfefac385e32f640c2e3fe298873ade499d92cca544769a88ccbaedb5cd4eb5e8e7a431a7b10cb0dce44f411aa3a22be6af7f1ef5b93f96b39c28a818225c7961dc5879318e9be4af78d59150260b3b712c8c4c615e4f0558d5d7abb9935a34b4e8dc050990c4ccf01a0432e2397266aaa7a635fbf97199e3dd6cb8ab9ceee4d1843f01e42df99b7b94179272eefb5e7453450e17b2efe24e3b585fe8707101d3d26e7d169e7e083538693066a2cf45e25626f4766328ebeb180f4c9a80d5264794e3395ce216080940d8b2f6709d618e173e4c91acbf76be013ec184526dd9d99b2149c441cf1ec1c7daf170670d5df092b15e582daecf85d140daa23aeaa5008183d5ddf926b0c8ae0ca22a9c8e4093ad0df5874c69c34b912671057b6afeda2fd41e0e223710ba8eb4d28afe45de7a7bfdf7a5d6443da901e2c2c966ef093056c4f62c820c8a0bd8c9c28344c664db4ae049971d8f089bffc11fd4535874c046cef36fa7a398b3ee6410b62b59f2b7c91d2a1d851e94ed0af4367f3a9aad84e12d9fff68aac9fde91bf2223dee4ea05d3500dfaab6f91203b3ed3f2346f1462240763462d1db99e8bd205ee3afb116f9fa13790c13011b967994cda0d7d65a4aefd076870bece6b2b3f2ab8907218701ef6694146c2c0ea8b1d7f40e95f744b957dfc325397e7ef1382", + "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441124e9634ac86d5322a89fe272dd95ec8f0910e46f753f89c72c622ae351ae9ed29012c2b59ed2e47dbf67687e99852bec5d63ca1680e3ad65cb5c747a9c37eb900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002240e1f1fe5145cc75fe7b253dd853cded77fb484b8be9d52aaf0a49098afcc7d24e0b65d370477cc168e835d8143177b582294e4a47357f372f960754b56b54f17b852c2d0067302ffa20e6f7068292fa3304e6e20e60a0c51ed55a2e0c2a2a615de98a2794725029dd283936e25dbbb2d8cf00dc4401eac6e834b094e5efd8e0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } }, - "source": "crisp_verify_test", "test_exit_code": { "crisp": 0, "folded_export": 0, - "enclave_contracts": 0 + "enclave_contracts": 1 } } diff --git a/circuits/benchmarks/results_secure/integration_summary.json b/circuits/benchmarks/results_secure/integration_summary.json new file mode 100644 index 000000000..c0ad6e144 --- /dev/null +++ b/circuits/benchmarks/results_secure/integration_summary.json @@ -0,0 +1,171 @@ +{ + "integration_test": "test_trbfv_actor", + "multithread": { + "rayon_threads": 13, + "max_simultaneous_rayon_tasks": 1, + "cores_available": 14 + }, + "operation_timings": [ + { + "name": "CalculateDecryptionKey", + "avg_seconds": 0.599410291, + "runs": 3, + "total_seconds": 1.798230875 + }, + { + "name": "CalculateDecryptionShare", + "avg_seconds": 2.123328597, + "runs": 3, + "total_seconds": 6.369985792 + }, + { + "name": "CalculateThresholdDecryption", + "avg_seconds": 1.93815725, + "runs": 1, + "total_seconds": 1.93815725 + }, + { + "name": "GenEsiSss", + "avg_seconds": 0.755760708, + "runs": 3, + "total_seconds": 2.267282126 + }, + { + "name": "GenPkShareAndSkSss", + "avg_seconds": 1.230714874, + "runs": 3, + "total_seconds": 3.692144624 + }, + { + "name": "ZkDecryptedSharesAggregation", + "avg_seconds": 18.895682083, + "runs": 1, + "total_seconds": 18.895682083 + }, + { + "name": "ZkDecryptionAggregation", + "avg_seconds": 48.057542125, + "runs": 1, + "total_seconds": 48.057542125 + }, + { + "name": "ZkDkgAggregation", + "avg_seconds": 20.904339167, + "runs": 1, + "total_seconds": 20.904339167 + }, + { + "name": "ZkDkgShareDecryption", + "avg_seconds": 30.160204763, + "runs": 6, + "total_seconds": 180.961228582 + }, + { + "name": "ZkNodeDkgFold", + "avg_seconds": 102.337581166, + "runs": 3, + "total_seconds": 307.0127435 + }, + { + "name": "ZkPkAggregation", + "avg_seconds": 49.016015041, + "runs": 1, + "total_seconds": 49.016015041 + }, + { + "name": "ZkPkBfv", + "avg_seconds": 3.839788277, + "runs": 3, + "total_seconds": 11.519364833 + }, + { + "name": "ZkPkGeneration", + "avg_seconds": 65.134843083, + "runs": 3, + "total_seconds": 195.40452925 + }, + { + "name": "ZkShareComputation", + "avg_seconds": 52.426543555, + "runs": 6, + "total_seconds": 314.559261334 + }, + { + "name": "ZkShareEncryption", + "avg_seconds": 112.963847905, + "runs": 54, + "total_seconds": 6100.047786911 + }, + { + "name": "ZkThresholdShareDecryption", + "avg_seconds": 244.367978902, + "runs": 3, + "total_seconds": 733.103936707 + }, + { + "name": "ZkVerifyShareDecryptionProofs", + "avg_seconds": 0.092927916, + "runs": 3, + "total_seconds": 0.27878375 + }, + { + "name": "ZkVerifyShareProofs", + "avg_seconds": 0.266464458, + "runs": 5, + "total_seconds": 1.332322292 + } + ], + "operation_timings_total_seconds": 7997.159336242, + "timings_seconds": [ + { + "label": "Starting trbfv actor test", + "seconds": 0e-9 + }, + { + "label": "Setup completed", + "seconds": 3.274390084 + }, + { + "label": "Committee Setup Completed", + "seconds": 20.259594916 + }, + { + "label": "Committee Finalization Complete", + "seconds": 0.005869333 + }, + { + "label": "ThresholdShares -> PublicKeyAggregated", + "seconds": 7204.022842209 + }, + { + "label": "E3Request -> PublicKeyAggregated", + "seconds": 7211.068496417 + }, + { + "label": "Application CT Gen", + "seconds": 7.746761542 + }, + { + "label": "Running FHE Application", + "seconds": 0.088362083 + }, + { + "label": "Ciphertext published -> PlaintextAggregated", + "seconds": 814.168040875 + }, + { + "label": "Entire Test", + "seconds": 8056.619484583 + } + ], + "folded_artifacts": { + "dkg_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000830d9d4344316b026000000000000000000000000000000000000000000000001d383081c39dbc5a000000000000000000000000000000000000000000000000ac70e435f22d64fb500000000000000000000000000000000000000000000000000005bbc150f125200000000000000000000000000000000000000000000000a8a546866290bb770000000000000000000000000000000000000000000000001fd3f2400d703cfb700000000000000000000000000000000000000000000000b9038d2ae3e79290b0000000000000000000000000000000000000000000000000001e3d48d51e5500000000000000000000000000000000000000000000000067a0471dd42faa6b0000000000000000000000000000000000000000000000000e9084f4ea2d5e512000000000000000000000000000000000000000000000008a356e94c183365dc000000000000000000000000000000000000000000000000000254af5f427efd00000000000000000000000000000000000000000000000238e18ad2a5a9480f00000000000000000000000000000000000000000000000bd3b65543dd7dc02f00000000000000000000000000000000000000000000000759321a99ec5a19300000000000000000000000000000000000000000000000000002a525effa8d9000ee44df0d016c13539e3e1de25cb3283bfa0110644e6c3060b51acf455c43f02d5202ac66917f20fae1a39f8cf51134df47884f67caecca680f87bdfdd85ccf0315bef50348a88d4c79a1b50bdc50c9882a2946c73cf72c563058759727f8a009db15cdba20a346d9491fdfdff4ddaf05c2474d9c1f2c4821a5e2e101b7b8e82e181958e78629f078e836c725ba08236958e3445a0dc31fc4c2202707b61c7d0ac53aa35319f776db882a6acee6b04a492720c30b527f6a209efbfb4b22975403a5568ec8e19525b52dfe82dfd9aaab141462570f5c39f9a42f13700ff87603118b076682b92bee70ee8f9b972b8cdeb9ff1fbd603352f945f2c95fd35184f70f989616eff536ee31d0349dc97067aa11f2ab4c8782c4d19a4b89968e13f69f208509774cc987cc232b93c9c49974be00e3ee21c6d743b80d823f9eb1ee13be236cf0e7b7aa0a5a5f4207edc057a37096d17a63c48f2866132c681a904108c02045139ff715913e4d22a696f788d1cb2424d855ef9bfe36f67721de67235cab0e4f4cce9ff0f3588aca137e0740c7dac2a980816ddc38f10be0dd37f01028891d4476773d637a1bee280492d73d68838af602126de7b85d767e835f1ec2f5f7015609620fb34c0980312b5b7f67ba6ad756f683152cd1a95e9e4c9a8fd58bbd1c0b2d262ca7d1cfbfc729424917aa0bccc6e667b7d4e4293e56552cb688b8320ec6d51d706a3d0b516eeac14f7b49e736cb687e82d64d239005709ea7a22af41daaba74d8165e869cf52616a224d38bf14b43f9365e25bdb8f5e3088158cc3e2ec485c6affc47a2b1a4a1d0b691d81aa7efeb0d4f243c3f9862a9b376e7648a2a1f40a23824acd2860b8fd4464a89ad9da06c090a2dc69564011c9749dde2ed15a551e0c27cb57298106bdf016afc08b87f0ac06032ee6860c10be94821fde507c4f9ccbfd67261a4729466f98ee1db61592af1fc7b39e2181034e27abc492409e069c23c577f4749acd5236e349f1c92837155ab5553d1ce276d8aba649f661e4ae3dcd8f73ba139ca807d90d6dec1a9b860762731186ba09357343823fd671a0a8440d758f2714b07ce0b6d8ee3e072af2f999efd2b2f4bd29a0b7e4ee2fb03969abdb773917cdfc033166bdd42ee8c0f0de8fdc1f0b959ffd56c806c06ea1137b28ee248c3176911c6a89f3ac4fbe9294fd2c25740790a660a831c1fb96109efa0ff705b5c893a9243584fbbbef285f05ca9370a3a352ff33e3fbb4ce74222a57e9df2068cf76844517674c6e6a188fa7158768ee6fb34da4c185fb830a8030b0eff418ff974072732b830d30df3199387ea05c52692283f7bcce83b46392ff77a2391ee371a20d92c00b3e9ce77fdd50918e3ca550e914a7a53ee6f8b7709d5a71495d8ed3e4500f7d429da6dc0ce8b1e10e8153d28ed7b0454f33cecd924540395148ae0936911fd4c376a78890ebe5d7fb220351c257b7bd4569d752023276726c1d48dc36a0147a3db2a69a24b00b54e87d42177e95503de125797ab2420f3fa31bbd5c0e70f3038b55ad7e40fbd4380e86fdc7fe89164eb0aacd59012dfde37496f6116d41ff33c74efb86de3dfa2d24cefc0b63c89d79e133cc29905efb2920c4f7da9c8b961871dd18fd44999a25e5dcccc9ccab601a2e675373e100c397861eb058b5755e03a51eae9d52c2e4d4995ae4ca18e4dc2233d7d7aef09e64d43b4813625ee86b3dde7f88897786e1416eddb163c124b159785245e69114691c2e2133c527da43f96a3ce84e6dd4ca5565323c6c315ad829d67ffe1c404621eb8bf726f2e29a09c7859bed166cb8ba83b62b89937330ba87944cfa8ca0ca6890ea5b94cf33b92150635f7eaaa4f6ba748de2c1511f5951f64b2020cc62dd083cfc17c88a46303505006aba555321be0a57109e342280647134ce385c5299579a2c5323a9de3f476deb15b2bef26ae534a4cc8ef85736d2e278da053c606e1876d5599770ec050ca34a7586b97509498768869afbcce36fa99b3bea7e2190eff69b5e545803434ea8ad62014852a371430a727701311a6f04fa47cb2cd08ca37d24e1311f454ce5d64f1be459f3f63bd3c2c5d2d8b894886deb7403c1915a57f7b0dc00c079803ca7502bfe4818087b1bee5e5ef561924cb46df8ee9af2f4791d0d4821ba79925efd25af9808cbb8277cd45e6c8b1c435290fc3a81816113cd7b0348fa54da05b8a621dc0216d78be0a5d5e1a910fdc581e4d05f27a011ecc21fad91def43ccce7539527630fe9efe81a8af34587cb9fee87f922e63d01377a702022f407844e60f563192d097fc190d4b9423e4e7b237edbe025c47b910c6da28d26c5f25a5025265d2a204a519b833f8e64d2a3a4c0f00c1c39ce69e1d0b89313a4d0a35ddcdf13ffeaf15535473b98771e39baf7e4aa6f927264e6119206d1b024b808af816db984825a1ab0c4ec9df14120dbabdcdf4b0bb4445ac022d4f53f6757cec1a02719b166bc272aa26fd3d5a19f053e13fbd00b5d67ada109d29051cd5ec728a99bc53a016164989493cef0a3fcd26825ad0673bf2fd9a17788433a5a33f5dfa3d26c5afbc72d8154c7ef45b0321decf426bc6f37e7b0e0493ee9e522db3775ec83b6d4c69585fa5023553e5d477f6e1ac2a80b4f0477a0f18b2c4014e7596d55b3e6cc268d4b3f0d265cf823feb97355ad804bb1510c5021956e6865c693615eccaa18c8dfd10fd643ae26d30bd4fd07af6309c8385af2ae91ffade4e050bb2a85681ec5eee4e55168bf626743731018ec69c8ff8574700456dc0c1b55946cfd78d2350072c21be9d3081f24bb64349c2dd8f63fee8440c5a2c18c8332898034b2f6b5c774f71d8a436168330e2a43d1501d35bf7264307009ae8c13c7f98a61e2b6294ebd04b54eb61cd67c868e5a70b247a82c56b5000773850ad4fec37329ce608029bf0091939a6a1b6b9f426f2042c0717b61dae1a416763e0be43ca69a9f855685aa38ca1de9230cc19b7a4defaa050052549512770183df9e2acc5a1723ce3d73b96b32c41adfafe5cee370a1e678fa79ea3722461dfd9aeb45139569f0e6f7a3c3d7f60013fa59ec8b7345fa311351a12d2140d8e6ed91a51176926a8dba35e2c65d4ac7320103427b36f20f3411ba8f04ee614427ff6b94415c230ed5f49545dd15a4e1df3fed50437b81ddfac5cf1165e6116e3e7fec6439f5f56494929c6fa96e7e6a49d999026d174126e0deb9eb11aa01cd1e0dca8ffee2d57bbb6a22e1393f6ebd5392244b30634971e9f38de5aa999134af1bc04a03e028bd552b71f42a2b798e649db9214c69412e408467037b7de1f4fd334f1c9f9c7bf1050182d4cb55bfa65f679a1c01e10cce60b0ba019b0a7211b9f3e4e5cf04297d83eeb51a0d4582534a00decceea4c163271f2696053e8164d2dad9506d5bfcb921ae50e0d91b96b81d4c3a805116e90e9c4f6becf24e42fa10833dbf0f0713f1b46fe67f689ec0b3d6e6ae54838dc2b20549c9fead4f317fa104e25740c58fa1089a411c6fe1140e07cd5e859dc3f4b10cad565cd35c21eb743d7d066b0216ef1222ed15d5d2b19901623f0ed9ade841181ef7384ed412f47fbb67ab1620be7c439652920a57f0e24e0489622a90ba284b0f15d8708f105dd4dbc8cedd61f619f19696f3d65d947ac5a37117e42234a0b1ac09891a97d2045fe954f13a507dc665b6f4dc1af44dca049b48f50601239d54963830057c21fea7fbc790dba2a482930e983d06cf20e52f841048ea23fd9becae3c6c56dea16d3627053072fd2eb637138bb5af7f1574e5ea375e8d147294672d93b1ab92a2e625c96a55982d59f2908793089c5d675fb63e56ccdcd0872735cc0c45351970c34f093e20663390986b19081d84681c360a40344a48044e228a23139c07de62bc0d25c0f844edddb2e17b82340e9d73f228772ee64c59f9746aa416f1405860bc6bfd996c2e61c9bc823024de7bdf863bc5133fd6ab0805c4c88ebbd3fcbb12d0f7308c4c486a20860283e6e2320e198f6a2d085cc8980e26f2e51a550933928e561229bfb72912cc955aabeea11b030d1c17551eccda5bb5f5bff83fbbd5013563d0f8a86a2d65ad84d5c95ce6c5a2b656b3b578b73f21d02ba88fe8a9d712e2afeeb9d7e0eb9c1a541f91ade3049ca1f51897a474235342a9a6f88fb499428e9770a22b2dd768a096dc5616a65630e49d6805da5c884ae7e0312ccf8feec24843bd69da995e08aeebb8e5a4c54b61d70edb1c5e62db5e3ff429ae5cafff81dd26c2cb92f24909acd104662f7d74d54466c57386cb437cda86fdbfa342f3011ac3251f702fb97585a11f54408b29243d4eae98f77a096a0ea94e624d152b8267e3d7dfeac3d7df0e8224a2f2d99102031ad8a74dfd347c88c55de823733b90632ec5a50f12be845c37ae121d1b0d662cf8961ca1227bef498feb4928655861f5672914a9fb0b568580a74142716cd5ebb0ce51c1c8d072f6dd5c981ca3ed106bef9c00c32e0246166d0d789aec5041f57d670fb2f0fbb4aa87335a7ef7a512cd1a8bb26b2d343de10f1b05957a69cb3e99e955b9aec21c4fbf7a4b5453c421bc106f05c610f438528f8e733d48e402f42600c1ae3b74318c41b722dd5cc6925154ed14a9928b5a96e2e4b4efe986e226c755e98e61ea76ec944eb78a3d69201231ee7b8063640dd0cd244ae2e598bded49282ed4d79c0f890c098432a534708246110b4e213240c5bf0026fd920a4bb45e2c574295ba581b644d13d762cfd0d43d638af1e48c7e08246e03fed8b6dc6c09ab358b627fc13faff5add1d19751abbdb7ea60b18e3f2b102fc3d30167795ea71badf50e36e7ae300dbcabd1216048274a5622365a76c5e7a50d353fb8e9a1094f8deb532f930fea082eeb6a4b31c1bb329608eefae298673490756fa62d97ca75d15f4441f1e6018de13991f3816bc02756edccbeaf4300ebffada8d6b6c943cae931a17f6a89a5e2b232117c0075f297211fe6a9cfdd0a4f32127175b900f81e70ef7e79e1d1e51e7afebd95a0c91f87a48820ad1236710841d0f4cad093f3173a2d3060d59d33d2de467f0072a5a51e107eb89a2b8dc2ecd12d77db3ec7513ac16154c2f1ce91861514e615724f19f85a4c2c2b99629eff7eb549565ad3f5217d6ed6b00eb83c75e170215ea04b957bb50d43308a0e5993d64b0341182bf7e615835b8a971f1d37d18630b46287d062a775a49374c26263f01e4062cfdc3b934fd8c22029a3d44d0760c116a242d2751cff8a77d499e4b9ba267e85143e5f1a59195d98cc13ff0a4fb3ad7c90907b712c497a116fc6f365a7f4f4285f7f5926487491a9cbed80268203b5e53074c7c275265fea6cbd5555f42dc8f8f45122a9f1a64120f0ed5f2243f410041026d88d6e4179b61e5d74d705240cd0d43730cf5cd444824aa68219d38dce9192f1023376a1d43ccf70c0b7382b4253eecb6aa387b83120cdfe6d02788ae70b3303be8647e4498ca34cae02c5fff879a7d4106c8ece7153abc8db46c12dcb49a23c6dd66ef69852617850c188eb1e9f6051bf69841624f9b98c909b54559b1e42f85ee41dfc9ad92b00495f0fcad184d54f6b3d5bc239541e0a4a1b13750efd50ea8779427d2fcc35a52cf61a4786f9ed6f69c9c842dbb60436c1c8fe999c51e2ace7522b27e4b3b8caff8e1a4ee75455e869e24333e541db868e616d6bcc60720e529e44071d6f59aabbc1921a7a28a662cf5756a53fa23bf56fec80b6ed6b90a65fc7af3019b9a937f10a38e6e9f505a5560cd594fa6c42b52db56befdb9160be7f0de83d3abcab2d9efddec09d43cb6da76a733ffc61bf9db3281f3bb6c3a27bcb2167b53f38d25f1e1b85e1a55f53dbaa39ed09dd99da47dc62ac3e8676d2179043618a209e0cf54b7c1d85281897b86b7fc4d2a03faf6272d30339c9d2029841ba7c096a9f52c3ffd13d354f06ca15bc394b99de23492f7da1757e3769419ed503135e7736210e1f37ddc3bcfb9b7627354bd38b55f3f3d326f2e8a761a17da2abd212372bfc5fe8f07033d8bda07733512982a3092153286ef6f95e4df1cf934d31d0566f00c1b1f1186bb66a3b3083c285f7c08b21eee1d2733784d442063bd18b682dd4e90921766318cb642e3789a1cc4a6a191643c49a9b5be21fa004f66731f08c82f2d433f0ea3a5ce0d4fa2ebe5ece4545d4bf75eef7387c3622006f028a52b5bdafd3a058c16068a4d331df9ad12888e64e8b52b12a514c0e51dc2c154263d1399b3108002ff047d94c86256d801891f8c3d0cac48d7d5503f2bb7074d74e23b2bc7056963f5897a95d9dc32006c6a259166474287b15063b900bc8f035a99d7cf793ef4d706050388921536d3b3bac47fdff272b1f34f94800f0b6de358640c1f7f50cd197faaea1afa3dd005abe027f5406a1d43b4fa753e1bf29ad3b1ddb946fc5ad5aab9c781f13a9bd7fbb4024fc769271c1617b160b62821f77d6b20c09b826540204521241540181ff1156eba68f62c3807d74fb6b82a26ed573505f10bbe1afabf79d4d85accfdde58bacf25838f0fa93d87c276d72f7af912395093ae881e3be578d3dfde5675a7df316907ef4e349b8e0c493c481c7a29583b0eaa6ef46c964cc64dac3aad7c065a79ba92687ce0a98ee8cdb6361a14fce6daec621048466b4a6bbff5176467f07e6a2b69d5a59ce0127c77c05912d44efb3fa2a2d643dd0631c0c420303970e67d144185aab38122ee4d89a180002c26533406e07c05fbbfbbb148d6212908b6368226ea7c7d5b3e839910389e0099bc3354cb8d84d8a9effe2cd41ef669540fa409d96d787b622cbb530f643b09aab6a03e9b83f0a22202c68286417e48731d44a2eb367308d472ab2d860c8803db08bfa695f3f2930a8c664374b927c41dcc3c9c2fcf71e1c3efb95fd866102947e9746b2cf78aa01b14cb5db1b082a352f58fa64c4506028b405e82ed6ebd0826c6541fa085bc93ac86d87386c2042f07b045d93f017366d6c1d93ebcedd014e278d3835050677c5d46e7378734d23c51e67f1fcaebaf567698e4eda0f70e15dd2e99d51ae126ad71067d10cab934a9f0d0f88b6b004e1e1e1092b7cd460f1a170e7efb388dd92ff079c964f5f0191a51b99ba304b159294220629427c66322d192e3cb8014a8e42c965e9f09703949fda898bf106f70e3200faaae85c86e10f790ade8f2875364d93992679319355f0415beb31b498a59f932bcabf37de62a6e3e2cc8ead181b76d7f2f81c89665e5991486881ed6e85957f55d87c4de2f0bb2af449984fad5b85aa1fc465a345e5c098635d36cd5df525866c9925158c120366487c32261f99551943f7bd9b828fd0f805c91af36923afb9a1035a976cf29d7efe8355bfc2823d0d9d26252bcf99df9af15ffa66a2a57d675b8cf6494e20615cc6f195c46ac770f1fe2cbb8f966071ea08c126a5993126a291ee908a96a2214f44d6e3bab7a1f8cc9a535d86930423ab2be7b7f50ab026ae178a7464df6002c08e6f95f946dec9d918fa7c701979e5e7277efd92c2e0391bbcdfba23e102c2d4162f5812fac7806769430c50cf13d041229d170f339e9fb0765ea57b5a90afcb342c8d26ea08634abbcfae382a9292252b2722c90071257e8b6a3542a7d1b202c88abbb094b7a2f6be1d22ea647347d0f43ab767873da3d12382713ae0b132942d7950c80d15ea5a933684f30593ed3517517987dcf7b800fb8eb8dc64b07bc25686cc77bfc09b2d71f441bcff96a0a7c7bb947c6079080f694243530d600844e32e68804d47077fed9246ee42860b7d03ba6cccb59b539553e212fad1304214624e71fa2f1496d36e6ace06ace6f520af8bc12fa6907234b65d64d3a81300ed8c5074835551bc7cbbef0b6dec93fa8eac69ceb2b6fa787ed2b21cd15851840cbc48395ffe7276e88100c327fbf0d4b7ca7d9e7a4a1f17ad4e214a4fac82a7bab24a3c7a0e15438197bad66ca888729446d342811f1aa9a76c4452531e605e7fe0f6cf94dfd74cc7bec4fdcca0269fe0f2356608838073b1a2bcbb0bd130f19d0156490dc9d40165ca992696c5108931f1a0735fcb95193f56f5af1c4a70125c502bd7355b66681cb150761c244f8f1c12b1700a4aa873545c8d44f1dbd2c27884cbc54e96cd0cb82a908f5cb4f98ca4848fd7d6607c7c376fa5fbaf5b80634c59c38c194fa0c158398b64ef453fa5d1d0eecd13fb4c47d1452ed75bebf1874785457afda78924f0f4f191a26da477702053e6b4ea9a9158aeb8be5cba01eed0bea52ba039d30db1021cf35d604bafe3e53e81d7d7a2f54cdcb1a07a1de113f1b5a613d9e4b57b599353128a4e4fd25b865767590ed535d0f8b64a5ba6f1b2ccd91bb5128694deb43752b489f8ef72aa7850b83c921f56b27dcbcd801d8293d9bd61050e6ac52b47d25c4ba3eb7c3268719971b9c5f6b6285e7de73ab861c8a071a0b61d854c12f15e8bccbdb3948f41330dab8f1e1b46401fe630cd9590cbeedb644bca3ab31753ce8759476832ed9eb828375fa41106cbb8812a4ab3f2d2917d97686724f15012e3aa224edbfa79b5703723b9f1da9d8f298e7a424e717c15f97c6bf2975729f8056bec981a39d6c055d27c0b46166a6ada05e93d96d21e8b83dd54e3cb2488d3e4750dc0cc64a5a3f5ecd99eb8598c57f36b698f19105f585c424c2f0c2a8bdb04498b691ae1c26302705c2fcdbb7ac34181f65900108f4a30fa53778b73db14e6d881314fee1b43d119dc7500b68eff4b24650bb7510e8c3728a3ca4e710c32347395b4b203884db0191c4ee2039e21aed587ec1760ca67d37030c26656ebac257d53dd24515d20dd84a5ef465978759d706139a0c259dd389daef6ffa3c56f3052ba2da2a49996bd9e3ceebb79d7338319a51569811ea7cdd52331d67c99185bcad199e61682a180a6f16c021229de73dee8e9eae0e057f1a75896831b980d2376c6baa22430d90781298cd2c76a3f5a5832360d30c6d8c121ced3ea63e682940893df32891a0f20fe3771ac18e8895421c624da426b14707eea022d5814f3d774ecc970a9b1ff47bae53a335b230c2f29334f279215860b96d5c4e332dc5d521628505256bc95ffcaf7e6af856188f82b31088981c8aa702e18474e5df8f3ecac017929b8ac9a6a8f475ddd59c408014b4c8129001e5d9a9a60c8c13482d0837da1dd4b39c69b31f0d514838b6fae82c89e06c572d35b1b48563839c0992ce91307b4d837ed609baf6afb38d48e7972b8b5b99f91fdeca4c830613e7f9b72bd083efe820181fc523820f15ed63fb0822b9230c570859aab904fd73648275e5373ff1af6f61712b1c54db6d978406694e9b6038650f79671116f91705532e3dc721ae876dfb1bd00480f5eb58caac1171e79fc9652aa650cf76380bb290d6cd3732a2d080cc997d2da545fde1027339d4646c4dec09214ce863c782bd94e0a31b28b4752f7941d3a92401bfa4e37d81c61fe0f75e02162aaa21eb2c66e4dcfa0bef894309aebf66b8962fa9e8afaeafba81a283d0125ca9f4cfef741def31d6098c96fbe5bcb15fdaf3385c768f2f8cfc183ef6662a46f7b706b2bea3d914c8e070012297473589bf3e9669b9b4767073c80f7a7626f3ca968a920ce519da4e4f48f62a480065c015d4865430ca207d6582947f7403bc218272d157440faaa13a39e22f45866cad2e2dfdd09b7f7a79b1b21e0dfc0bc45b781f6950f78d4631281d285180ddc7579f12d53da5254468947f88c64d2404ca4392d6b9483901ca83f488b0eb99c6d9e61855f940e349618bb4cdda120cb9fdabf9a482fe39eabdaa2b4f8698a1085a949dc6ee0fc4da4baeb3270e7a153fc2f4912de3780b345be03f1e15bb753897c2a0c7b00b7e6a618c7b3c20e10439bcc07d2377b5dc924375ced34e7d7cc8ba6a0d1fa6697a457dc6e612bccd0964a3ac2316c29aecd74957ea9bcb5f4a70a655a1999fafbd95380d763c261813f0c6ded6f4acdb425e3047a64f187e195afb7aa9399bd775e29d3578af140b224bc801d54c95d3790079c8393ed98a7bc3e5acad2cbea47887b0163c1544a40966e04884b239de2dac9e8aeed580e5f956f8a8e1fb671e75d34e5fbf0054ad0a974b331ccbb54c8e8585d5eb41a5ce017860bb71135724903392d6b2f0017819c9ff87ff6948eba679e1bc202394505e6d368ee5be6dd25b4439c7f75a96501ee54142e584831644a3e8241064c3eed654b6207aad54cd6d499674b43450d811025dac2d3557cb347773d2bd3295ee079df0f1b3efc2fa0a9d82cd1ed20bde2bd6e34585718101ac22e513c10675f3aa2f9bac70f9f870566b54d8ce8a3efd2b60b63b6b6e16f8dd1c78424aef184ffff1a53ad572390d8edd42e12c6e5e9d01c2c362010c018763f2154e1c0a5a03fa54832572603c918595c280962a7d2c01d9259c30854eae881636f2256369627f6f380217b7aa0801cb8f5d486fff811a30fbd4048a0c81d9560ad1462dc5981aa2d8e1fa9c90f2de629b8503a127900b2fa796825e2c150ac4fd3bd7d195cb67af638e3c488b981e0312ca79e038041e241d9cf8886003759b85cd3c669ae378e8ba9422ffc09858b4f2176bd9d5b722c3f11e8c8f7cb8a3d231024e60f79258315938b9f8ab8974c1f0221e8571e00c98ddbea1a84f571064b2477455777ffd10e902a33dccf434232a62c946e557076ff7bc613e5111167319e1b3d2234b3da40a8b4d49e00b4a5d23d953bf2fce089f706c73c7b0e82c212743ece53b7c96cbd5445865fe705539dc7dd0ef0fb60fc255d83f113467e1d8eb4da93dad481732cbe0d4b4a9769deaa83b6abbfc84149e3502435b22304a721cea21100cad0220b078d0f93800b8032d73e592f88e2e3aeda6320f26cd7c4ef4299193396343c12bdbbd9a87cb52b18f2e08027716008ccf50ef396033799f9fffbe9d32766e7d9d3f4d32e6ea7ccb08cec6f2d97227954aef0752083f3ca2d5dc02994622d1e06dfdc7f043b4e947b6ce3e217b7d27b0d8db69361d9a78937e99143d81fc0990dc4dc46583f3cf73db704c2cca2927400622e6bda6427adaa4183ce35abcc598c5526a69e26a3c6dc4af36eb6c160ab48cc09ca6961d808bec4d6084741b1b2f33534553e7d24f630f0bb640c118062730001bebb4e5702ce2fa779104caaa107e1f1899fec2374a7f27764f7ede21a5e12cdb37b4ca76b6951212562a105f92a315b950d8f434ff416b1b9a1b2422542f057fe7d51597880e645ab1714fc229f68002b3d1e269ceeb32969b353e11ac49ca87ea7f88875de12309ddfe3f6cf4501522e68ecc199db40b4001867c123a1e6a293a691d8151ad766f0130fa0bd970aae5ac366b886257423afdd0761a28cd4a57083ebc02a3dabd01693859a12b9cacda074fbe5ccd2ab834b15d65093c17d5ee31d0c180f8c74b42e91330ff9a9de6c39f23c4e7533fb63f284c63304f216f7c4ae3f54a9c627b8d0c4630fa6bfdd917830ed5d3c0235a6e418692237fdcdeb42e7ed028fd7f95aca773bd7573c654e6856604ee0d9d7fa25f6cc91b0021a21d95c9e2ed43c38e92cc99d0858f791f33c7c4096b4073a50a605af92e9a31efb3fa1054ae2b053573c05cf80189cf9cb1eeaa65561a54f721df77ee2ddf01652c0435eb7597ea08e0664181b3f679113845f0e03ed829431541f05d203def0f84f22abe9fec00c6052b290ecd0db4797466aff18461037e202ee54806e756fbd0e3076fbdfc66fe4193483139f60f235dc8f5cddfe98439288a7753155bd0112d2d9810e489a5d98f38170d50ef95978af50b478fcc04ecc50779f40050c9dd0f00897baf1d4d1b06c9aac43016048cfffa660bab245fdada960e4f041af6a74318a9dfea942ab43a0f96759c9202cfac134071297e13a8d2f85ef508175c4f36719cc2a3a4d21955a3402abaf3320f83fede6a173c7414b5883a8f13d47610689ec9fc2ee58b124fa5bf5a35545d41457c16b009cd2a3eb7e109f71ebc8c881ab00c42acab3415b19b798ebc498b1c3082f4569d01e3de6a0508cf2ba3949cf042821c3acf2cb6db150a88b36f7ba6684d39fbfcda0e807dac34871ae08b9eac0b61e5a37433aced9f98b6561b794309d4baa95ded5888f022a8eb1d9f79b2d8e5956fbf4990d68c906bd82638d806a842a601783e4d4597765a60252c2c6119bd618c2ba6d69d08fd192f4a3fd2c3b4c7f010d53cd6e2a7423ad008ec05208111a54223a5273410057b8981019bf1811b991bcc366049469605b42fd28cd0b86bde221037d2b8fd45cb0c9b27e48386a963a84f61dcc58440ca032597de6c3507f1e648311c5525fd00378d3432955cfdf7eb87fd3832624d912a2696d383a5f0090b5ae652a07570818d0455a505c3655c003e79ed841cd1a02119556b5f142928ab98a491ca0b486300c0e126bf9308797faf4d6d4f096c8fed301fa9aff821908059e36c2a2ff6e783796e33140ff21e46a3e19320a162c0a80b574fa11c5610721789046457a8e122dbbc31f9db8e9d60eea6fdb78fb62e002942999bb7ee575ebf42514a77595e1177199575464f7cc47e535f0d0c564a3a1b2e5e37b1d9f7eb0404df692657f7d4d5aa7ac1418d3bb1c0055afda07e6b1e1b6bc8f49f0e6255250aec766ba36d26c78a34c64c379689c4bc13302fc0a2e90923bf1e1915ed0ca385aba72da2f48566569f21a88069fa4600df845309ef7b137e09f44bc8215c0b31d1191797b2a789fcdc460bdce0b58eef3ec23e7f46ee09257488dd2f164e17a31fed823468e23e7791d0897daf3f937ffe7d05bb55511e1c417c6f2fb6fceea5ebfcd854a23ab5ca8fdc7c04908d8b81e436207dbb1f18da479741bd2883269c262a870a23bfc99ca1a714ddcdb769d695aa747bf726173a91cf40d052149374a8809cb89c2ccc1751c07e2b2bc4e286774bbfe4b1712d38e2106b4546a9af90a3008d709994d0adaee76450273eb6715ccb2ed12824070533ab886efef8291c861e327d1198221667f380dd075a86fcd21d5f7c3ff7032d213496e23fc2845413df185d31f73a6198904c94ddccb0fefa0f250b599b0223370e91052e2b4b71b6133793f6f6c9a5f313efb18f2e88001e561b480c7f128af589420a68ab0dabbf4118cad6fe88586d6759c1395cb199cf6590a1d4fd052eb2aab72f8746d2147262fc3c1a64235a45ae1d171c31a917208adc36b84013fe1e6b33fdad0187aaee03b96a3626e4d5006bb0ffcc91d1d57239ce89461e0570641c01456e1c92e19a0054d9c812de26ed8cefee8f1e29903867aca772a11cabe48a842659044e170f37774282a95dca132c110aacc8354be42019156dd92a790c670bcf81ab066867a237e984e6e51b28f0b9be32323a1b76eef7d25c4d0e2079053cbc8ba35f2b1823b437a526f482d892c240f8e8258eb73f29d77f700fa00cfa645e659a661969d96c5d93a03239997e24f2a3d551f74804e235bbc12117b470959358f27fc14086c9d9494b8f6074e98cf99ba4d98607f8054e01c30dd270176d233a81f079282ac2d90d61e6278c0bc08fbff1914b49e432e0039b2b9d3af036e3554540363571f6cf94384af6a31647e2416da794a816dcca9e930ddff997ba2d5d6ca43b8b27ce0e5ef64097365087bba89d904ed998f250f93f134d50ffec261e5d928b0e7ea27594f54febe371db232923a7dd799d8de591cf005909f50abfb4f11d0af2edb4899ca7bd57cf2ab1b8172af3d1cdb4b32072121ba1274c502ba63577953f92f9dd4f715fa87411d6501435ef42d64c3b9941c11c5104477a3a7c216138f889ebe0cbe7ad8687c9cc998c83a0a5d64cd37b08a80411ea0f65a76c75969c095f9103dc1d950454549f95eb2b4139617dcb0c7d9e21ff3f9786b19ff2456a4c77191118917a82179807d42e4b6a03ea7ccc6ce3462f124adb34301fe90c49423e41e8a0f135b76d6653a107f8f91c9d8a3fe14874283fd2c7d4173367a0a729b8c378f396ee73c3310dd807b80a12c3e1f50e76bc235179e6eade026a5b94aeee06760fe269c187c0ca04cd22f8a6933f617ef55221d07bbd98ac54cd8d7e4b63980dadb35296060af0bab5cc9969a7042cf6c8b0000ddd081697143999fb6c1e12bc4134602fdae6180e5a69a1b54d203a0e086b272e29940a796957ac570af02ccaf8e1cbd94013607d2f7bd4be7c466986d14d15b90f5f649d3da06cf9a2d20d684075971fc6589466ec9560f78f95d63af4500e621998656153ca8ba44402b31b19cf7eb932adafb783547e2e019e152fe3361b7e76c63017866dd5eeee8c7ee7c569a1dee58a78b8c3ccb250600c9aab1cd706a210f1d7c892ccf6b68f6dc42c86f8993a9634952c4c9cc3ee0184a64a28a60afcd2605a76a47a34885bf7cb398e70dfba201aff2221f55345464ec01bb36a2ca81d2a0e0e09280964d5c06671235fb5d3976aa2c31f8bc74c0e3f6f9fba500e7650be7a2791e8f7bc78c1033f6e3e829af8f5664e7703f0b48ad9d3e1de8a15f7812ec86a5d13fd88077241559c19a4cc7c174741c6f091405081a809562b1d7b74b4b4c7fe9d36b5d542c28135a6072ffc5ca0d746fb98588ad7d35df9e618b80609be85aec7266ff9bcca42c3714c9f9f2724fef38f698e63d3139c29a6", + "public_inputs_hex": "0x1d420eaa08a65528f470fd3e2a802913b611527f41fca008a0ad4e97475078032a555ccad424037773cae7569cd26f46467d9bd96c32334af741c911096761830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022197e95de61c6c2844727c848aa819fe89bff180954ba01135f7e3d285aa3d8e240e1f1fe5145cc75fe7b253dd853cded77fb484b8be9d52aaf0a49098afcc7d24e0b65d370477cc168e835d8143177b582294e4a47357f372f960754b56b54f2a318f2fc85748ea90c49625631654288c77791d8dd0792e201c748ca9863ac417b852c2d0067302ffa20e6f7068292fa3304e6e20e60a0c51ed55a2e0c2a2a615de98a2794725029dd283936e25dbbb2d8cf00dc4401eac6e834b094e5efd8e2bad40c7a2fc975f2e4811607e4d5fb72361dd1af1bb2364be799270aab5c6f623db21355d312ad82ff6334e39518d7aec226005c56d124daf506a44749cf370" + }, + "decryption_aggregator": { + "proof_hex": "0x00000000000000000000000000000000000000000000000d6343409c0afb816a000000000000000000000000000000000000000000000000e0e3142188542d9d000000000000000000000000000000000000000000000004bdda217c121af9d500000000000000000000000000000000000000000000000000014a5db1afe856000000000000000000000000000000000000000000000000ee178f82f74d1cab000000000000000000000000000000000000000000000002e8d0a46d30478dfe00000000000000000000000000000000000000000000000207560c01e3450dbc00000000000000000000000000000000000000000000000000022788c7db5ddc0000000000000000000000000000000000000000000000099ba154d1691f0c0c0000000000000000000000000000000000000000000000077a57fa84b59575440000000000000000000000000000000000000000000000052b18c02725e6860800000000000000000000000000000000000000000000000000017e9657c0fc1c000000000000000000000000000000000000000000000002b224b4548754d742000000000000000000000000000000000000000000000009134fbdf2459e11e8000000000000000000000000000000000000000000000007ae759187042674660000000000000000000000000000000000000000000000000001b7072ac05fcc10fd82a9f5e13726dda894346515567a79c225b241a718f1b252ee23cfcb8dfc134749cb199d7dfa121b0233c0bca54919eea35871367be619fab7d4acde565f21f7d05e4d6075633ee1781849710d0cc9f901e277b8147885e33549518fe8c9235394cb328d148824ef86c283f67c33bd9d74125ce290de790d17252755f12a2c575b654f3c0128b45fc00733497bedb1ab89208d38b1062fbdcd9874d1a1102203a3af11c6d2beeefa926f37841cf1766ee9c1fd8fb937fd7ca88bcf091a3b0d693f463de1bc4d89d66c527f61a537f8c5e09d43384776febd12c1a0b160192419f01ad42306732827a9e2b737e59e99429dafabbc4b63fd1eac9ac2d8f50324e028c3bfc9cb7efabedc43d2c85fd8454cb2ac6edb769ec5aaa71a6813ed252ea7767466292e673a4791482b20189da899063637b2fb233fe7413ebe14ab48172ebbec7b1577ece1ca982dfe9bc31189268e16381b3452830ad955c85334f723b7cd29f8459a2bdce9108984d2445710388a4ec18f02e22446ef9281b115a80a16fb591cb108f0398b7bdd4b096354d07245988cde80562a2e3997dc8d77ac05bada7a25ab6675abb5c42348a44a313a519ade461c43aa3993e73cfc06472e252e3d75992b831f25d123331077a32c38e1377c7e7e41f360cc4f9cb84e70fc047c37bac2870a10065df9c6c9405302c93374fecd0753fc9874bb9889e7e2d8056c734dfc773c2d255b48cb1ba153afd8e628b1a7fcb0ca36233ed95a92e6960811d86a8a694956d28b0187c66038d4aaccb51e0a164bd42d83fc40fb48b8a61af5e281d9149910f3494c80f943107661e722113d7b9a6c0c1deab0beae72c60ec45189b66a1679eca9165ebc7a629d2e71e0a594277d0fbbb1379fa345c9a61c5b614ff22f7abbde64cb1c7c49431e04559ba35828a18bfdba63c1169090a409a9f16759479cadbd816a6eb1116a9a4d0c3ad1b5f36f304a97c7e87643778f0c38118f46b63bbd48cf9b4e18bd76663b71ad6b8312ad607a4664b2f47259ed009c81da4d44d2d89b736a3ca86649ec926b8d9f5ce807ea302b1ecbc0349ba0010534881c9a4b14b496d7dd5146e97bff9978f74eb7cd73dfdde685be41267606e74867136658c65220b3f1515fad8fc3d291f636b9ba4a03f4e288464e246a17c606205cb08af4feda633d7e7358b8a8c1e3a9bb7cc3e0089717bdc29914ea0b923cfac7c47dc0b8d04a4ee9071fc9317c266eec4ccab59ffae46a9cee283d05e0a63d50303298db10d4af510792f740a8bbd35be7057bf1cee727e79394c22a8e2545755f8a0599a1e150671f54850bfbd1743210499c84c3b77b4d1f66431069cb273078a2e10f1f015ccc54118eae036e1947b49f63342d2e5cc69ac3db0e6346f2648d7fec2da28cbec5afb3314ceda07cc2c3ef10078c086658fdb63229c49d8545542435bd4d3b1696c001df587e38707a12cf521214825cac7af47d227e93ed63f59ed33ce031cd61931a57bf28f14f457a815be7267cc3c210ed870dcb1324eecc54a3357207d5d9d2c42815d5e7b2a65b4c9d5f1e208a9ed0a6b4235e122935a8843159470d69ebec0a3383369dee35693d475148f18247247c071a06a44e4197aa7a02bc80ff31e3209552172b66163935d82fd56dc4a6a730ff173fc70ce51c6c9dd197840a1e873489010c6750c0f7c05ba0de148c871f50570359ebea3159661fd9333c2db2b4f5041249f8dd96ad6ecd2623078086bdb0e51b67b47a31148be3689e5bc49025c1182f1ea881ed3c65e72c2944f0928668171ec2d7741c74f5047a6b13a71eb54058979c872ce634aa6b5dc6e060dcc85d1002cd3cbd4ab0b1076ff2360427b4157bf24c8d965d6c836962a84ec8315cc713080b314982a7345e5a38ed87768e95095ab5b39c8736cef5710baa273277ac2e17f55debdc276dc29eb726c7a938b352124bbfb0a07c26605f144d404bbd2bdf149594defc22c1a6717c5147d2f36dd017d5524107ce84c6e97b7a143e29d52f25022de025b573b9eb662e6c3d09660e4d0b423a16661e9cf66f44eaf21945692150a6292c541bb691e59f8ff4fb579f797bc5d89b3138d8a7aeccedb49729c724beb14ae3f33d99876f08496a48a22de7c436ec88364ba02e10bf3c52236ea913e8426d7cc3e2d38c861f8981014f91432d53089ac70e114b86d4a60d150e51107bdebe9f1e40b98059a4313e5bff2e5b3200c6ca3a0545a8f115bde4fb7d7107b2010c1aa5c9d5ae36db4f703cce98712fac6a633da3874a71943809c40cd7260a628aede79ffe3799bbe5d49288b947d1d067f4ba336f26bd7862510ffb4328331991a2f89b9f53a3620b32bc7bb50f76eb9cde2cb2f9cf42c4a22df0c0e20331793e2f642f142bae542cb7e2f0fd200db0b710d3fd3c0f4d37afa38b8d501fc34640655f2776937aefd2c0c15fa5dc91fa5de878ed805b700436d8ea62ec2061cc0c19517812cd43acb92e01018dd857565ff19d40bb8f09a5f2753b26900f1ee465a4bded176bdb8c4cd3589184c8c80c0b95cfa3484ae2655c46508c4b1e06aa30e32f43f454846e4dfea668903fed3bf23762dabf7b4d7fdc33590fa3010b8aa4bdf244b628b32e4468ad96056a848209a65f1c42dca8318754332aa109bbfe7a82cd199fc831c48b5439c09209b31247b258bb665d2190407ba46dad014ed3c854628e09e8ba9da2c4e2b1e658a6b56fc772a101531810ba1efd61040ede249e8bbacc5b7f064e3a0a89f98d64bccfa1d47c52bafc19f615c4df0fcd059b763205544ba63668706829151458142db92203b996a171fdbd9dc8016f54105b72228df5503f7a4484b4e99320c03d7d8d384e83ad9cf5b9ab322a9f81582f48298a3a781a02a0fb4e6a7b116dc94f11cd919b909ae8fef369dd4a7498252a0c3cbf87c8e91ac7e56d9bcf6ddfec337df1e6f2caff2fd04489a0e15f51c00c8bab2bf1e204b2516dde8c6212fbc5d519398e1d7ffb0d3ced8ccad27638a0183755e45c97ed7e8496714a425b0683362ef4cefaa0acb128464c50054393010a3916f001a49abadfaa9c44052829ab1373491eb5afc19c448cc2ec2384cff003b6ef542acbc10237a0355395a4828bf9c356e66a92f998a9860477393e2ecc09d9a7501d79a694699ccd39b0fc5f7518b6ef187bea3938e24ac1e649107ae7134b4819e221010ff3ea8ca2aae7cfd8c913d727339e5e90d8bf9af431f2767f229d00d4bc9a9ab2708b1a268395b66e88603b50f8ec614b1ee8f042247191be099258078233ddbe8699093187d4b87238b8503be1b3a992a66efeb3c15bf46e114045770bc9dea0af8d1b3b9e7f89ad0f0f7b5cb58347f9bc31a1f5b749125503095d5ea015e6af870476964d02d0836687d9e205ff986efa3fa05eaf42567813be91e7d92751fe7dddce9055502b2beab3e4e3b9987491834fe202b41a16142628026d775db7141e97e2d4144abfd41e23c68dac14669bde63aafd40d4a8002c28aa160a0b5b1f57bcf17e056e62e9a6a792e75c194faecf8edf72ab65904b061cfd14a239bc808454c33b080a44af18784da9335cf5d3de85828c5b2a91d113bf19bc7ab5f87b921f7b88712ef3895fbee836d87dd311efc22d394dcb758321c9d1a26147d519764b79da0bc929d245fed23e95e58281d43dc93a611641ad104e9bb58a706ac4f9212e22869a7d7d816c3afc5f2b9275babbc2353dc59c332db15dde7753b62322c8bcf8d41b72e3bbe6ff0a2c61eb466e5512bf1a8be499301fe18941e16b2122f0fc390e191cf3a4532c849b39956f3e318c907163810611034a1a296a7bbe66780ca88c6f599ca09c82d83d70e1bfa4473776b5c068221194dc907822535370338f889825f36a24db7a3b42168201e5e80264e41e7569162cb3669ee45cf5c0810dda88651c91cc32fb2aae51c18f55174129409892050248d04cd731434d63434389f80310114dc92993c9b39e42550954633cf31d241754f6dc46a21f7be676f914feecb63bcfa9d839638e8fd140acbbe7e494540a1da5b4f31a302ecde922b1a10aff437aa96759c3059fa958a3a6e2c50361306d1c4a7b7f63a4abe9b13738ccde8195d2cc4fb4c3c85ad53c78dc8496283d0cc601396dd75bfacebad9ded60880f37b46bc61c87724c7b8c0513f1783675e4d5018f7f30a9115e2b95cbb5052e03b3111d90798ce5272e2c6228c165fce6c347c27711e7de6d91d0b6bdf34677334c6e8ca47a60e0b7bbb5a0f01a6724174d0cf0f38bdebf434e84d92160285043af5227e5f628012786f658f53dca24e3d3cda0841e6a5b1c9be5b9b898e5e71a0eac8825cf7d8b4f38fb0138dfda4cb5a9e5b0cc2d6ad4868dfa422efff32fb32a6535891e60413f524f001d727d786f2970e04e0809642af932031d727274d05962dab59cf469ab5d400f6291950cf78382218b051a65adfd64e4e81a5e31bc3dc22dfe95a810750fbfb0e9bb9e230aec7a3227e15527102ce7d9462df9e992926f691c129f6e38371aa044411006660b45b22ed9c9c0335ccaa9a3771614eda0ee18a5b1293cb713f3e4cf32209bf2b2be91b52a3e0461b00b50bc24212e7a0a168cd4a5670eed7735141ffbb2530bb11151d70bfc2ddd7bf86ec678546a0ba985b6152c5b427e31c612f298280263c0f312db2b751667a6b85ba0fac6656417340203010f463292039979dfe7bc30897160e633531a0d52f9a326a3aee24c35fbccdaa387a801db8f6d9ca2cf6b6641eae06aac300aea7c12bf9a28f3b667beb873af6f9caceec3fc3f0616dc7f4bd22f4146614c7ed9acb39a3915b92ac5b7787a877f46033e414b721b49d8d27e5ab892415cd864a75ef2e316f4ba10efa47a4559fcaa336afc1d9414c0204b98cc0a70626f89136564bfec778ef9807939900337c2616739d4a50f3be2c71830968412b0790e7e1110b375a19e3f5ffc7b3a605e187f41bff4a6283828996fd3f26a213a28f6e3ad328976ed2b72d62ad54cf51d8215f993325d697137dc2a4c1e3c80f6462158846588d3f5b8cfdafa9b1018b7b1348b150b76bcdd0640f57fd2d862dda4449740d5cb065e00bc50146bc70b3dac6a6e9103d0863af505eaab860361ed7accae9e15089da9d1d801ae35817a5f67a28a604771cbf3be04ebc9c20e51368750ba4cdee1f00fa042d805ab474446a90cfbf3fc97a20fe1ca5e4a6d588266864684004140b5150b5cdca08014cec724f1aef668d2ba67254a53f2c59d50ea76d17c1e2160bcab9fa7540b366abfaf5f8413244eaf950547f7571cc057729ea749b5fbf56ab428aab3ed476cd4f68b3f41eac270bd6b29fcda4f75626071b1a20be49701c43b4b16437ccc9fdf48a62fe1a2663a68c352e147f4ae8844c2807157c23509fbd64ac8ef2db22655f9745461382cf08b2d3cfdbf28081198a21ed719565dc566fb084e14c45856676c2a3a981576fad4bad652a20e85092a128f13027717bcd2bfaade88737b4ace18b183076e1876c817935ef5d7ba8b0622f6b2441c65d5d4c293d3a0506639a43c5d085c2df2b838a27263902349be4951f7f12272801748a9b3d4245de5e60f77cbeb1454b069a9f476e59bf36245722244ac46a6da45d3406581f44125c5661200e0d92ebdaaa3d14e973d2618ffc9b2081a5ce7bd73efba7488ec506c08e8100329c8a9f4db5d1d94165c5e0a21f202a8aee42247f7d031bffb09f2d852246350848d82a5c139169e8c8d39e6178bb264a9dd76aea3c0ee71750c7a9287741eeca96cc3e2418426d0e24d5665a4dc22cf017f7fec4b71e1e288e9efff6882b3fe1b39b4a527403b8d87a77b1f7b92511ef72f0386ad6da5c92005b739f5bb3c6aa212453e8e6d343ade9cc24a752631e63d16b0a0d0f0013302d8a6b592cac45f107cbd67975e6c4bccbb48572b6290fdbf02aee0467e7e24d7274351a3fd001627678697c6d18fb80fcc5cdb2b79e294219cb7224ebc6a5ae6ec05376afda73fd323e700aea6553a139f1bfaef34111e8014ae15ce5ddc2568eac8f8621f643468697c0f957c13d13de82457e4310297c09ac3934c2a272a10621472fe0deb9eb13dad684b66f5b19a420d8c010a82fc2de64ae10f7ed94fe5a610ae0f8889fe1d94f92544858c65ec64b95055ac11c4652efe064f85ac337332ad95955bb6db02f2d11040cffb5d6a8f9e632a93b14045aabcba545e42a03bbdb72421e4e08644e587725d0bf29d3c8a235bab183158dc24705ff40a5f24f8a0ea39f30aef722faf69af92a500abef9e2f26a2b642d76adb78616af6e74608fd27de1c8ce87a090d832f57e13ec2534abf164ba0b2be6d35cbaefe0366ab88d79d0f152a4cbff4a40a4dd1585cd47f7c6d39492721b4819f391ffe75d71858e5e7f3b7040d6d363761eb4b596aedbba067d8c4add0183eb7e4c92d2f449f9287ff1c0a8062ca1d719ef98e276c98ed954559047ec1aac319dd0d0e925fd34e61f3b450c6dc69cd7f50d4df31733d0652aef9d20d91b5aa21fe2b9a3c6915f614a7f1616959cc3fc32c5187f0dd24b0f51b32272ea072d7e084d62c3324dabd4f1985dc2c0aa88915960a5c1785ca8683207dbe4792d9d900add917b458ae42c0c8f66b9c414c484644e56fb083a7731d336d210060d5bf4c1b5f807c4692ca713632bd87b26ead2b7182937890b091a15f42d6ca2011026280c64f222ffd8629a17136b4c7a6fada3e2742fe377434073a9cee2bb03246938701a602957d1bb0abfd402035df562b6ac784c99647ac645c7958366136f0024347b1fd8bf330b4d697b97838393c0c91b82582343eb58e2f9d6b9c82b1387eed1f819c4d9a45a7e4d1ec5f2d2f0a8fe5aa96705c2058e1f62b5b2d5254c98a089c8f5eab8617604beb94022770aa9c76fab0cca170d5fdc2dbd40e628da831293d1c24273d9523a420bc585f93d4baa497e68f258121f9647fb2ef90bbad294f96003a9069d13d95465fbfb65362e6c70e61b6056e5b7053477fa0b17f609298e716d5fe9e20b2e49d5779a225f535ffa20c88bdc387a1ea66864d62571705f8745c3d21e0b714826d23644b10d5f3c166f1bd704291c20e7f685e8245e007dd62da8e45374824a7d819c48aeae8cc9beb2988bd8cb3cf074c7af0f2ec4fde771894a79f484ddee1e2af510dc80843c64f2dd12b7fb36d69a4b323b1d0aa5f93a2ea384df044c2132470d4c5aefe263fcdf47e68e9d26e63c81dcd32a389e21e2d56d771c823017fe31533809c3b5d3016afd6f95329ed4db23daf0106cd2e9f2addd7e0f013c1a32c3d5eaff36d796800acb744179cbd788a15a3c037261f29e401178fecd97f8fa01daf54700ce5982b1d58e025ed6ecbd300e7107afb7af7e7ebb538d40acad316ad54db0bab5ada811e395e0ebe6cf74ad149629c2fd131d0ef7d2faa4fbb177351dd1e68135f5ad97bfd6651a2c98ca8ef85926aef7180b5d563c5ad7df270d921a79feafa12e533cd9b8d602fea0ae16899729fc9de73eda204ba93c5c60ec0420cc4bc9d06b189045d9c12c71bd79e673c40c7ccd521d3ff61c7eceb8e965c00de62c8a32acfd1f121c0ee841fa2f756f0618f2d4d6ac96d7bd74f67427e347e2e760446958f9115ad9a35b530e801071be246e5576bd91e99ade8d75b12fbd1a43dd83960b318f970045dd374984b535e72bd2ba51ecd03b9396ad32e9fc4a8fcc22b203b32a45263a795786f4fbdc459b0659c4f1cc8261dfa55ea5ab693197366697b6ade5d4340c8192fceead82ace629a7472f3b13c28a954d467990509f4ce8ca0d37464673ad92a13c2715b7db55250d67b3a7e4d9a735099f8aee1544d0e6fd73f0cfad9c3aa5e40b0e2b8962561ec35f1ad2b11aff259d79d1baaba2fba96eb834e76a9c80b364e97b24307a281424aa2fa30be62314f75d116f5c131ec32bbd3d548ac60e287531ee45b88a9911e2292468a9077985e7f9bf3b9d7c9c7f4f4d58a034168a0846edc8fd6e821919bc426b90b9d31fd35ea2b87b4ae485c0684ab37528cb0f6319003a27dcf72e1bc9e5dc54f4a62cae86cedff569653518ce21fdcc660bbd5e7be989b268663728da72800734456991bb11783aa00a75d9d3e930bc9355f763b4c3d040e1dcf01955668b29288a41828a44bfcce4f3d3d409fd71f61b6a69b12757debf0d01692551a363188bca817da75832de2a3115a69e2cb747b0cb16ae52e6ee572c5de717941f01982ec1c364c7cd5d4d6eff0e3b03c68e7dca325c1e804b2e0abfbfeb1c9c593a923554ecd202ce87adc8dd2f5c4866d494f148edbbd7496abe6faf5023d53378720ce63e06078b8d9e84ca9a1d2a65616bd2def3a8bef72908acca0a10543ea597c8d6d636236f8faaea56d55a20c9142f080147a46a88648bd9dc11017aa88cf3adb1e5c174be8ce4b43d33da7b54a2d92514e12b6b768ec63bf0c31f2a9605389352931a3b69a1f26ac4c2163544780d60fcc85795256c6afa280027b06fcce4b557599d94a87b5c481d9a34c331c396df9656fa89ba922dae138408bffe3ac2706d43bd7fb1c8e56f3718bc24cd0b9e9b0ebe94080cb5eecce6480f8c185f442142926ca3172b2e19c03c0722752911cc8a6c7206f3c2912787122662900584b849d650e0c4eedfaf8187238a97f307266eed20d6e0b6ba01b9f20046fd636ffc52fc2d5daf18ebb043f41bfece62514c98854a64ebc2fdfeaf7c1cec169dd44365b740df2819d9ad1aadd76bdf6033173f06ac4d778fa9d4855822dba8778bcec03e6fe23987933ac5841cbc60c642f2aa3f59f1eca01f7802481358b76b89c085167d1b82e5e893efb5c368bdabf60c4d65c8b526e791bc70fe24da05333484e79a43adf9468afc8a513e75578bc37681732417d87d3d1a1e5a1d7680fc28c20793b079d2fbf91f06483f9faf0d3ed1f7e0c3414ca35b2f25e7277eda67942f851dff283b7a1776dff8760a130b2e4a95fa7a494e866404815d1f8313141a02a6fd2aaf2204dbf452587087026b47df4bde2c459632697f3909173803e820b6a810ead209db8c49720978493b40daa7651c88244627d27ae18420957e21543565fbd8367917180042e123042789206e7a0f382f05630a7233ce23870618eb29d57048ea6baa35a13e7775ea499b77fa2b2939a21948c33c49b80eb128ad72c44ec6b2c43ebc0ebed56c4d357759a372cb724cded062b46bd9a7242e8783d21021596916098b8ba9210ef0df0b8f5065757dfd22b3564c2cf1c62776f8659e98c20f45088864e86e85b8e61803d2e2e8db08c5597633e2884b1312f78654b323134010efe0a5a22f96ff83ab4e467746b698b8d2d68d2937d3132e98b53f62eb12c772cf6b86924ea8990b7fe9f6ca76e36ec6bb71334d5fe7ac0ff44d2a4c39e0447d41ee9144c125ae86e1696d83894163c929b99d5657682c0ccc8739c3c024b7d3b35be279dec63ccbd81e8c0d6e63debbcea29386640dd127985d1724b1ef912fa749d00325fd280af6eef3c77346dd5e2022dd02963caf2169bc8168aa63972cd3c404977532baec258ca30873d54b585b7de7de78081313ad920afd58a88ed6de63c31e93a3c05693b27665cfb4daddccb2d584b0c71f0577d99ae959e0d3295f3b009a1bc1b357cdbd35bd564a90c10c57a52c4d5c9e175b5bf6cda85e75a362d53be71619e033f18a912ac2bb171a8650b6494f385c23cfb56b3e56656966c1c3ad6aa4ff5fe93108e3aa5f266feb88c3654015fee429eeee7128c5e0b683bf8670ef76f2064c82e33acfa4b98fb010516c9758c24c08287df25152362f76b084441cecf158a6a03c74473f7ded3f9a280283f3a94306a6b182ca1c741819fa8676d33f15534ac596a39d184f208664084e86f69f491355d22dec6c7fdd47db8991f40363b46b90b495a01bb12e79bdfc17c015222c072641d13506921a872ac44c9cc8d108225e2aaf54c7d51d7a2b05ef429931aa01430a19e1d3fff8f96d9abb6c0e0cb3f645c059329e2c08162c99890102ba0d05634e00f98c8be1b71cb16bb2844c4cdcd67eea6259c5a9d668c058afd5889e27f0261c1586d2b4cbc5948a248e38240aaf1b6ee10801c93b9f6bc130cb04460efbe72cb208793fce34c92d5cf696958d7d560e5ff6847c635498a769eae2392b0e3ef9384f3ed5a8fc649537d71b6c540bcdbc695313c2d581d999edcbb7992ee1be226490863613c815b8677279673ed4659589212807f82da56e940e674601240ccf06909e2191a4d52f09a513a0acd557e70ee7bb5df0179cd2659547b10fa1792b0ccca44cd07e4b82df1a2c5e017d2f8a32c0842937f182a9f354a63516308aae017cf8a00e316b678fd379054cacb79841e0801c32e8d34e5b52ea8b0c8cd36caf58534592739dbb0ab2de7572923ec1622a98428768e440b38d4ace26bfbe8863b8dca57239ebb222338467db5400732d172f716e449e63c92fadb419e5644af6620b3258e48e198f2ef956a6856143b35a756ac2e35cfcb6eecc7d178c6515c496180fef749ac8e977fa63a28fe6dcfbc73ddb360ed5709fc9b0fe026c4635a79e7f4caefe5299dd7cf4b0210925079bae38b94a1cfd393c36b5730d3b39ddecf9213ed09c1760211d7c8299f793f875acc0e8a1e444a7c8009d5d0df95cf94b07d8ddea9e064bb63e544b266a94c00d0c91b75697c7164fea0f912983f360a60797fda997f5f370162ef1847ae23ebfff5e72a8e8c719631b7f8e24c08cedaad805e39e5373db066ee5705cf40a4641472965ec2e8165fea29ab119fb1fb534d5183820622a1d4500fceb3ae14eac2b420e084526dab4088f174c03abd7cdf5e33ecbcb6c6b1f09875a347c283cb0920de180cb615648c29c203f0ecd1b1a3b9d78569171956034619df0c3f6bce2442e302b4a7a0d6c321313491247bf62042d00eeb61610243fc11ad0d517806fb5f9ae448e7facf517db96571a6a1af751ac14a6383f96870460481013a08d296259a69405f1b94b9c50af4e262e4a32bde88f8a1c7abf78808893ed9a0b293eece0feb9e5fb3c86cd4f874b0a8851b7ec202d182ce02749dba88d816f94c2304cda0c56573114472ae4789903a9782552283c2c2b88ed75ae3a610b32844cbe7e7f7c74f5216fb6cb6615cc2797978cef7d47016bee6da4c77e9f60453cc17e44724812dc958172c38e98ba2407ea8b08e0f194575cee3effe062c4926bce85ba7e338a9a3fce58d4e021650d19a35f54d83ecaef10cbe01579973ff5bb6c07b29feb89ee137864ad11a2a70cb411e2a5b220b3fe8a74bb8d9bc4b624dc5914e52b9ace98e7671e0cf5e92b19536b803836dde90b9e384ffa4d590e141d96cd7944b79c6fb3d80992fc108702956f27608a987c9947ce3fdd637773787e0f976bee528e7ff57a7fb94fb361268bd81710fe3a615437e23e557ea5c485b4a6dbcd89e24eae87ebb9ae61eace002385c62bc8c9c1925ad79428be87cbc883c29c2bd9bfca108086de9053dd5a27999b28a3b0a8e41cf1fe430c3a035940be16521438e35fe5bbd212b8d0bcfb0135f7b015e51ad8ec8fa8df12cd077ad2bcf7a705889b9aa6674aa84c0428eb1ce7c1fa8d1b1adec22d51cc8a501c42b95c783dc1320c9b4d0fcb6f5dd4506b206f292e5d06fa78f52666675fde9819ce5dba63fa92ea8a6463422461f58e622d8937aae3718f509e1cecb3c95c9c82ae33ad610f692d7df28bffb8ffd4b3e4039e63003aa372590c543591e7d89ccbae71b74aa468a70da3db0e3ca463b15f0e6f4cdeb5bbf5ec3d736f1505610aff03ab11756a701f5b77578daf8989bc322dd5c44335a39dae704ad3f23389a598b98b69642f6cd7fa1830b998d64dc6a3250d7e6609e26e1725a4f6255ffe0e73e002b4aad16a1ab58b3fdcb8a26958830810ead864d8a658780beb619fab6c34e15199c1197968c99b38a5bf174478d413830e0056c5c2f967af9b3d26fb050519d4800bfaec15e7f13a94dcf2c5a2bd1c524d5ae0d73b30261003402d404f8e596ef73e98c0c4a6acb82456870f58671d138fdfb25ca284ec0793739a7cee577e6d3ba319efff2cf9f22b90f604e4f7014c701b5b3651d06ef3f3c3d566842801f26b1a8cffa425ec7aeffe6c1205932807754ec92ab14d58fff617ef19940a7e40c95ba9414628d59e6ea2fa9cc1140dd37f315857802b79f5d1b31c3b076de22ae95fdbbf2850886a0c671a67666a0b789aaeb6190fea5776179f028c774445d9c61c76dfe1a263c30a0ce5880bbf04378426e45dced169fdf580d0927fe256cc195db8122edb0732eed159a32cc72cd17f0ff0775670ed47492ab73e9bdb1646d1ddf6fac59a2f1698dbc00da9fa24dc2ab6ee98dcbd0682385e98342ffc86fc964c46b89ccbc2e990c68a761169037021867fd84d7db8c3a74c2a31bea5676045a5d33c4f525d51c11e01f58d200f0fa35b54f19c81087074ca714fed679d10f181f9cc2dfdc8cb1ebd703ac7200150fdd527067f0bc99b5b785afcb640874b3f62159de99771e6a86310818e5f2fb0169c55188588154761e71ffe774e208c335942d4dbe4aadf295d59297039066fe4bd1064d8ad040ada4cbf1f5cbe7b80e29396dccc2e0c93e4c1e0f373db107e57b560504f1e1bafce78380cd492758e1616d3076b68ada6dd12ed8adbdd14e14ff30a2ac375956f6087d8a68b13539c5a45d2b3de89d08a7db022f688050ff38bc3ad29e40c07a6159f119da20b870054811250aeb41f835d074b948a6b0f6f2f89422d726d91317c14441ccda2e382d0cf289c03d98aff6b3d34934bee232323cdc38dbb69f1c9092ada5e3a9cf8aa6e130203f1dadcac0ab7066a3de015dec2ab95501c4ce019c7cf444beb5d20d0e31b74e319c170c52acc6feae34009bdff8a7a5e189aba127f8d488ecec7bfee67c0e4da40da08e1d216c95e4e531569adc78433ec670379654df38bd2ba311657bd0273f3f945c45f7c9883e9042040c5b6cf63fb1069b8e0046174d371d03eb6cdd9029575e42b419a8b72380122ed3efddc9233f58b6c2dbc2a694d2b79011a794943f1a99e6603632ec4085927adb6976fb676e768d1ddb26b2c88158e8cba7b666ab6a20b030432ca67c8eb29c3b535066e0f779fef60ecba39001047452fe610643fb4491c13b86dbef2f409b504bb782009166f4d3069566271c6cc026ef64cee56c321be4aef2e665d47030a7fcc5527f2235722880893ad58c7dcc873095fa719bfbd937803dcc2788302a5ff8a658c1426defc4915c2e49e49ac66eb4e661d97eb9bc1c19d03228a58003a38e29ad1f40ecef9edefa3c9d86d6fa481d8bcdffdf1de0e419883f488bf2684050e1b465beca794930b7de04f78f0001bb18b954352807a99200f935f08133200c22324dff58e9f920bb0e54c8781c29ff6466cd26ada6ce05255248138001cd0f79242fd0768675144caacff113ce2d470a5d98f9ea44b6fd446e8511c1bd7c61a3d26af3415eb3532dc9b7b243b34752c63ba0bc2e81bd6000af3ee3e2f9409ffd485289bfb3e1ff44d8b181e081f9f948aac37c0d7d535cbef1a42501a0050b1ace19cc1779e23acc5aee850bdca8fd5591bbaa08e5b94d30df3f6b32a05139aad16899b7620a46d0be03c740e38704090e4d3d584aec4eb2d56f39a1573706fe29dae924284cffb950843d5e3090b3b59c9ea76a1a2215bbcd869712c7129bccf788ff4ccf5d9f28673b69788488553de67c648560a49f98c9054a30968dd170b7f9ccdc98147a7b6b0552bad5bb39a2eea0dfd942b320ddcac5e382ee141dd1b89eb46cb5e9da7537f63b77523abab01e9574ad161a911a896b867123735ad4c98de40f373bfd62165b0c737953c8c816c27142cd245917969bce31163936dd6680031e303c4086e9c8a6de7195c51fcdafaa9626f4691f201eb851e943c2dcf5a5e90005783bba67b6478fd637e43b5dfefac385e32f640c2e3fe298873ade499d92cca544769a88ccbaedb5cd4eb5e8e7a431a7b10cb0dce44f411aa3a22be6af7f1ef5b93f96b39c28a818225c7961dc5879318e9be4af78d59150260b3b712c8c4c615e4f0558d5d7abb9935a34b4e8dc050990c4ccf01a0432e2397266aaa7a635fbf97199e3dd6cb8ab9ceee4d1843f01e42df99b7b94179272eefb5e7453450e17b2efe24e3b585fe8707101d3d26e7d169e7e083538693066a2cf45e25626f4766328ebeb180f4c9a80d5264794e3395ce216080940d8b2f6709d618e173e4c91acbf76be013ec184526dd9d99b2149c441cf1ec1c7daf170670d5df092b15e582daecf85d140daa23aeaa5008183d5ddf926b0c8ae0ca22a9c8e4093ad0df5874c69c34b912671057b6afeda2fd41e0e223710ba8eb4d28afe45de7a7bfdf7a5d6443da901e2c2c966ef093056c4f62c820c8a0bd8c9c28344c664db4ae049971d8f089bffc11fd4535874c046cef36fa7a398b3ee6410b62b59f2b7c91d2a1d851e94ed0af4367f3a9aad84e12d9fff68aac9fde91bf2223dee4ea05d3500dfaab6f91203b3ed3f2346f1462240763462d1db99e8bd205ee3afb116f9fa13790c13011b967994cda0d7d65a4aefd076870bece6b2b3f2ab8907218701ef6694146c2c0ea8b1d7f40e95f744b957dfc325397e7ef1382", + "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441124e9634ac86d5322a89fe272dd95ec8f0910e46f753f89c72c622ae351ae9ed29012c2b59ed2e47dbf67687e99852bec5d63ca1680e3ad65cb5c747a9c37eb900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002240e1f1fe5145cc75fe7b253dd853cded77fb484b8be9d52aaf0a49098afcc7d24e0b65d370477cc168e835d8143177b582294e4a47357f372f960754b56b54f17b852c2d0067302ffa20e6f7068292fa3304e6e20e60a0c51ed55a2e0c2a2a615de98a2794725029dd283936e25dbbb2d8cf00dc4401eac6e834b094e5efd8e0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } +} diff --git a/circuits/benchmarks/results_secure/report.md b/circuits/benchmarks/results_secure/report.md index c02a463ec..0f232b173 100644 --- a/circuits/benchmarks/results_secure/report.md +++ b/circuits/benchmarks/results_secure/report.md @@ -1,9 +1,11 @@ # Enclave ZK Circuit Benchmarks -**Generated:** 2026-04-27 12:41:40 UTC +**Generated:** 2026-04-29 13:43:47 UTC -**Git Branch:** `fix/configs-circuit` -**Git Commit:** `eca330d9a59f5433c443a2880bc82aeedac8681b` +**Git Branch:** `feat/benches` +**Git Commit:** `36c01c62b86e2527279842280337f2f4724d2487` + +**Committee Size:** `H=3`, `N=3`, `T=1` --- @@ -13,36 +15,108 @@ | Circuit | Constraints | Prove time (s) | Verify time (ms) | Proof size (KB) | | -------------------- | ----------- | -------------- | ---------------- | --------------- | -| C0 | 287764 | 1.60 | 26.29 | 15.88 | -| C1 | 2432074 | 10.37 | 30.21 | 15.88 | -| C2a | 3879330 | 10.93 | 24.41 | 15.88 | -| C2b | 5739750 | 19.84 | 25.13 | 15.88 | -| C3a | 3764144 | 12.67 | 31.34 | 15.88 | -| C3b | 3764144 | 12.67 | 31.34 | 15.88 | -| C4a | 2564001 | 10.29 | 30.31 | 15.88 | -| C4b | 2564001 | 10.29 | 30.31 | 15.88 | -| C5 | 4395328 | 19.30 | 29.97 | 15.88 | -| user_data_encryption | 1678200 | 6.34 | 30.13 | 15.88 | -| C6 | 3001847 | 10.46 | 26.15 | 15.88 | -| C7 | 128310 | 0.53 | 25.75 | 15.88 | +| C0 | 287764 | 1.46 | 25.10 | 15.88 | +| C1 | 2432074 | 9.37 | 27.22 | 15.88 | +| C2a | 3879330 | 10.95 | 26.13 | 15.88 | +| C2b | 5739750 | 19.54 | 26.31 | 15.88 | +| C3a | 3764144 | 11.16 | 27.82 | 15.88 | +| C3b | 3764144 | 11.16 | 27.82 | 15.88 | +| C4a | 2564001 | 9.30 | 27.21 | 15.88 | +| C4b | 2564001 | 9.30 | 27.21 | 15.88 | +| C5 | 4395328 | 17.68 | 27.28 | 15.88 | +| user_data_encryption | 1678200 | 5.81 | 25.70 | 15.88 | +| C6 | 3001847 | 10.47 | 27.29 | 15.88 | +| C7 | 128310 | 0.53 | 27.59 | 15.88 | ### Artifacts | Artifact | Proof size | Public input size | Verify gas | Calldata gas | Total gas | | -------- | ---------- | ----------------- | ---------- | ------------ | --------- | -| Π_DKG | 15.88 KB | 0.12 KB | 3037824 | 202192 | 3240016 | -| Π_user | 31.75 KB | 0.22 KB | 2972929 | 386136 | 3359065 | -| Π_dec | 15.88 KB | 3.25 KB | 3549028 | 188124 | 3737152 | +| Π_DKG | 10.69 KB | 0.41 KB | 3037922 | 175556 | 3213538 | +| Π_user | 15.88 KB | 0.12 KB | 2972869 | 193468 | 3166337 | +| Π_dec | 10.69 KB | 3.41 KB | 3549077 | 186764 | 3735841 | ### Role / Phase / Activity | Role | Phase | Activity | Prove time | Proof size | Bandwidth | | --------------- | ----- | -------------------------------- | ---------- | ---------- | --------- | -| Each ciphernode | P1 | one-time DKG participation | 65.70 s | 95.25 KB | 96.41 KB | -| Aggregator | P2 | combine folds + C5 | 19.30 s | 15.88 KB | 16.00 KB | -| User | P3 | per user input | 12.14 s | 31.75 KB | 31.97 KB | -| Each ciphernode | P4 | per computation output (C6) | 10.46 s | 15.88 KB | 16.00 KB | -| Aggregator | P4 | per computation output (C7+fold) | 0.53 s | 15.88 KB | 19.12 KB | +| Each ciphernode | P1 | one-time DKG participation | 7204.02 s | 127.00 KB | 128.56 KB | +| Aggregator | P2 | combine folds + C5 | 17.68 s | 10.69 KB | 11.09 KB | +| User | P3 | per user input | 11.23 s | 15.88 KB | 16.00 KB | +| Each ciphernode | P4 | per computation output (C6) | 10.47 s | 15.88 KB | 16.00 KB | +| Aggregator | P4 | per computation output (C7+fold) | 814.17 s | 10.69 KB | 14.09 KB | + +## Integration test (`test_trbfv_actor`) + +### End-to-end phase timings (wall clock) + +| Phase | Duration (s) | +| ------------------------------------------- | ------------ | +| Starting trbfv actor test | 0.00 | +| Setup completed | 3.27 | +| Committee Setup Completed | 20.26 | +| Committee Finalization Complete | 0.01 | +| ThresholdShares -> PublicKeyAggregated | 7204.02 | +| E3Request -> PublicKeyAggregated | 7211.07 | +| Application CT Gen | 7.75 | +| Running FHE Application | 0.09 | +| Ciphertext published -> PlaintextAggregated | 814.17 | +| Entire Test | 8056.62 | + +### Thread pool (same process as integration test) + +| Setting | Value | +| ---------------------------- | ----- | +| Rayon threads | 13 | +| Max simultaneous Rayon tasks | 1 | +| Cores available | 14 | + +### CPU-bound operation timings (tracked in-process) + +| Name | Avg (s) | Runs | Total (s) | +| ----------------------------- | ------- | ---- | --------- | +| CalculateDecryptionKey | 0.60 | 3 | 1.80 | +| CalculateDecryptionShare | 2.12 | 3 | 6.37 | +| CalculateThresholdDecryption | 1.94 | 1 | 1.94 | +| GenEsiSss | 0.76 | 3 | 2.27 | +| GenPkShareAndSkSss | 1.23 | 3 | 3.69 | +| ZkDecryptedSharesAggregation | 18.90 | 1 | 18.90 | +| ZkDecryptionAggregation | 48.06 | 1 | 48.06 | +| ZkDkgAggregation | 20.90 | 1 | 20.90 | +| ZkDkgShareDecryption | 30.16 | 6 | 180.96 | +| ZkNodeDkgFold | 102.34 | 3 | 307.01 | +| ZkPkAggregation | 49.02 | 1 | 49.02 | +| ZkPkBfv | 3.84 | 3 | 11.52 | +| ZkPkGeneration | 65.13 | 3 | 195.40 | +| ZkShareComputation | 52.43 | 6 | 314.56 | +| ZkShareEncryption | 112.96 | 54 | 6100.05 | +| ZkThresholdShareDecryption | 244.37 | 3 | 733.10 | +| ZkVerifyShareDecryptionProofs | 0.09 | 3 | 0.28 | +| ZkVerifyShareProofs | 0.27 | 5 | 1.33 | + +Sum of tracked operation wall time: **7997.16 s** (often much larger than end-to-end wall clock +because work runs in parallel). + +## Raw circuit benchmark JSON (Nargo) + +Source files for the **Circuit Benchmarks** table. Persist this directory with +`crisp_verify_gas.json` (and optional `integration_summary.json`) to regenerate the report without +re-running the integration test. + +| File | +| ----------------------------------------------------- | +| `config_default.json` | +| `dkg_e_sm_share_computation_default.json` | +| `dkg_pk_default.json` | +| `dkg_share_decryption_default.json` | +| `dkg_share_encryption_default.json` | +| `dkg_sk_share_computation_default.json` | +| `threshold_decrypted_shares_aggregation_default.json` | +| `threshold_pk_aggregation_default.json` | +| `threshold_pk_generation_default.json` | +| `threshold_share_decryption_default.json` | +| `threshold_user_data_encryption_ct0_default.json` | +| `threshold_user_data_encryption_ct1_default.json` | ## System Information @@ -60,3 +134,8 @@ 1.0.0-beta.16+2d46fca7203545cbbfb31a0d0328de6c10a8db95 (git version hash: 2d46fca7203545cbbfb31a0d0328de6c10a8db95, is dirty: false) - **Barretenberg Version:** 3.0.0-nightly.20260102 + +## Notes + +- All nodes are executed on the same machine in this benchmark run, so inter-node network latency is + effectively 0. diff --git a/circuits/benchmarks/scripts/extract_crisp_verify_gas.sh b/circuits/benchmarks/scripts/extract_crisp_verify_gas.sh index bd4d34ee3..1ebf45847 100755 --- a/circuits/benchmarks/scripts/extract_crisp_verify_gas.sh +++ b/circuits/benchmarks/scripts/extract_crisp_verify_gas.sh @@ -1,11 +1,13 @@ #!/bin/bash # extract_crisp_verify_gas.sh - Runs CRISP verifier test with gas reporter and emits JSON. -# Usage: ./extract_crisp_verify_gas.sh --output +# Usage: ./extract_crisp_verify_gas.sh --output [--mode insecure|secure] [--verbose] set -e OUTPUT_JSON="" +MODE="insecure" +VERBOSE=false while [[ $# -gt 0 ]]; do case $1 in @@ -13,16 +15,28 @@ while [[ $# -gt 0 ]]; do OUTPUT_JSON="$2" shift 2 ;; + --mode) + MODE="$2" + shift 2 + ;; + --verbose|-v) + VERBOSE=true + shift + ;; *) echo "Unknown option: $1" - echo "Usage: $0 --output " + echo "Usage: $0 --output [--mode insecure|secure] [--verbose]" exit 1 ;; esac done if [ -z "$OUTPUT_JSON" ]; then - echo "Usage: $0 --output " + echo "Usage: $0 --output [--mode insecure|secure] [--verbose]" + exit 1 +fi +if [ "$MODE" != "insecure" ] && [ "$MODE" != "secure" ]; then + echo "Error: mode must be 'insecure' or 'secure'" exit 1 fi @@ -34,9 +48,10 @@ TMP_LOG_FOLDED="$(mktemp)" TMP_LOG_ENCLAVE="$(mktemp)" TMP_JSON_ENCLAVE="$(mktemp)" TMP_JSON_FOLDED="$(mktemp)" +TMP_JSON_SUMMARY="$(mktemp)" cleanup_tmp_files() { - rm -f "$TMP_LOG_CRISP" "$TMP_LOG_FOLDED" "$TMP_LOG_ENCLAVE" "$TMP_JSON_ENCLAVE" "$TMP_JSON_FOLDED" + rm -f "$TMP_LOG_CRISP" "$TMP_LOG_FOLDED" "$TMP_LOG_ENCLAVE" "$TMP_JSON_ENCLAVE" "$TMP_JSON_FOLDED" "$TMP_JSON_SUMMARY" } trap cleanup_tmp_files EXIT @@ -57,28 +72,49 @@ RAW_DIR="${OUTPUT_DIR}/raw" # Ensure recursive/noir VK variants exist for integration-based folded-proof export. # This populates target artifacts required by `test_trbfv_actor`. -( - cd "$REPO_ROOT" && \ - pnpm build:circuits --preset insecure-512 >/dev/null -) +if [ "$MODE" = "secure" ]; then + PRESET_NAME="secure-8192" +else + PRESET_NAME="insecure-512" +fi +echo " [gas] Preparing recursive verifier artifacts (build:circuits ${PRESET_NAME})..." +if [ "$VERBOSE" = true ]; then + echo " [gas] [verbose] Running: pnpm build:circuits --preset ${PRESET_NAME}" + ( + cd "$REPO_ROOT" && \ + pnpm build:circuits --preset "$PRESET_NAME" + ) +else + ( + cd "$REPO_ROOT" && \ + pnpm build:circuits --preset "$PRESET_NAME" >/dev/null + ) +fi +echo " [gas] Build artifacts ready." set +e +echo " [gas] Running CRISP verifier test for Pi_user gas..." ( cd "$CRISP_CONTRACTS_DIR" && \ pnpm hardhat test mocha --grep "should verify the proof correctly with the crisp verifier" -) > "$TMP_LOG_CRISP" 2>&1 -CRISP_TEST_EXIT_CODE=$? +) 2>&1 | tee "$TMP_LOG_CRISP" +CRISP_TEST_EXIT_CODE=${PIPESTATUS[0]} +echo " [gas] CRISP test completed (exit=${CRISP_TEST_EXIT_CODE})." +echo " [gas] Running integration test (test_trbfv_actor) for folded proofs + timings..." ( cd "$REPO_ROOT" && \ - BENCHMARK_FOLDED_OUTPUT="$TMP_JSON_FOLDED" cargo test -p e3-tests test_trbfv_actor -- --nocapture -) > "$TMP_LOG_FOLDED" 2>&1 -FOLDED_TEST_EXIT_CODE=$? + BENCHMARK_MODE="$MODE" BENCHMARK_FOLDED_OUTPUT="$TMP_JSON_FOLDED" BENCHMARK_SUMMARY_OUTPUT="$TMP_JSON_SUMMARY" cargo test -p e3-tests test_trbfv_actor -- --nocapture +) 2>&1 | tee "$TMP_LOG_FOLDED" +FOLDED_TEST_EXIT_CODE=${PIPESTATUS[0]} +echo " [gas] Integration export completed (exit=${FOLDED_TEST_EXIT_CODE})." +echo " [gas] Replaying folded artifacts on EVM verifiers for Pi_DKG/Pi_dec gas..." ( cd "$ENCLAVE_CONTRACTS_DIR" && \ BENCHMARK_RAW_DIR="$RAW_DIR" BENCHMARK_GAS_OUTPUT="$TMP_JSON_ENCLAVE" BENCHMARK_FOLDED_JSON="$TMP_JSON_FOLDED" \ pnpm hardhat run scripts/benchmarkGasFromRaw.ts --network hardhat -) > "$TMP_LOG_ENCLAVE" 2>&1 -ENCLAVE_TEST_EXIT_CODE=$? +) 2>&1 | tee "$TMP_LOG_ENCLAVE" +ENCLAVE_TEST_EXIT_CODE=${PIPESTATUS[0]} +echo " [gas] EVM replay completed (exit=${ENCLAVE_TEST_EXIT_CODE})." set -e parse_marker() { @@ -99,13 +135,72 @@ if m: PY } +hex_len_bytes() { + local hex="${1:-}" + python3 - "$hex" <<'PY' +import sys +h = sys.argv[1] or "" +if h.startswith("0x"): + h = h[2:] +if len(h) % 2 != 0: + print("") +else: + print(len(h) // 2) +PY +} + +calldata_gas_from_hex() { + local hex="${1:-}" + python3 - "$hex" <<'PY' +import sys +h = sys.argv[1] or "" +if h.startswith("0x"): + h = h[2:] +if len(h) % 2 != 0: + print("") + raise SystemExit(0) +gas = 0 +for i in range(0, len(h), 2): + b = h[i:i+2] + gas += 4 if b == "00" else 16 +print(gas) +PY +} + USER_VERIFY_GAS=$(parse_marker "crisp_user_verify" "$TMP_LOG_CRISP") DKG_VERIFY_GAS=$(jq -r '.verify_gas.dkg // empty' "$TMP_JSON_ENCLAVE" 2>/dev/null || true) DEC_VERIFY_GAS=$(jq -r '.verify_gas.dec // empty' "$TMP_JSON_ENCLAVE" 2>/dev/null || true) +DKG_PROOF_HEX=$(jq -r '.dkg_aggregator.proof_hex // empty' "$TMP_JSON_FOLDED" 2>/dev/null || true) +DKG_PUBLIC_HEX=$(jq -r '.dkg_aggregator.public_inputs_hex // empty' "$TMP_JSON_FOLDED" 2>/dev/null || true) +DEC_PROOF_HEX=$(jq -r '.decryption_aggregator.proof_hex // empty' "$TMP_JSON_FOLDED" 2>/dev/null || true) +DEC_PUBLIC_HEX=$(jq -r '.decryption_aggregator.public_inputs_hex // empty' "$TMP_JSON_FOLDED" 2>/dev/null || true) + +DKG_PROOF_SIZE_BYTES=$(hex_len_bytes "$DKG_PROOF_HEX") +DKG_PUBLIC_SIZE_BYTES=$(hex_len_bytes "$DKG_PUBLIC_HEX") +DEC_PROOF_SIZE_BYTES=$(hex_len_bytes "$DEC_PROOF_HEX") +DEC_PUBLIC_SIZE_BYTES=$(hex_len_bytes "$DEC_PUBLIC_HEX") + +DKG_PROOF_CALLDATA_GAS=$(calldata_gas_from_hex "$DKG_PROOF_HEX") +DKG_PUBLIC_CALLDATA_GAS=$(calldata_gas_from_hex "$DKG_PUBLIC_HEX") +DEC_PROOF_CALLDATA_GAS=$(calldata_gas_from_hex "$DEC_PROOF_HEX") +DEC_PUBLIC_CALLDATA_GAS=$(calldata_gas_from_hex "$DEC_PUBLIC_HEX") + [ -z "$USER_VERIFY_GAS" ] && USER_VERIFY_GAS="null" [ -z "$DKG_VERIFY_GAS" ] && DKG_VERIFY_GAS="null" [ -z "$DEC_VERIFY_GAS" ] && DEC_VERIFY_GAS="null" +[ -z "$DKG_PROOF_SIZE_BYTES" ] && DKG_PROOF_SIZE_BYTES="null" +[ -z "$DKG_PUBLIC_SIZE_BYTES" ] && DKG_PUBLIC_SIZE_BYTES="null" +[ -z "$DEC_PROOF_SIZE_BYTES" ] && DEC_PROOF_SIZE_BYTES="null" +[ -z "$DEC_PUBLIC_SIZE_BYTES" ] && DEC_PUBLIC_SIZE_BYTES="null" +[ -z "$DKG_PROOF_CALLDATA_GAS" ] && DKG_PROOF_CALLDATA_GAS="null" +[ -z "$DKG_PUBLIC_CALLDATA_GAS" ] && DKG_PUBLIC_CALLDATA_GAS="null" +[ -z "$DEC_PROOF_CALLDATA_GAS" ] && DEC_PROOF_CALLDATA_GAS="null" +[ -z "$DEC_PUBLIC_CALLDATA_GAS" ] && DEC_PUBLIC_CALLDATA_GAS="null" +INTEGRATION_SUMMARY_JSON=$(jq -c . "$TMP_JSON_SUMMARY" 2>/dev/null || true) +if [ -z "$INTEGRATION_SUMMARY_JSON" ] || ! printf '%s' "$INTEGRATION_SUMMARY_JSON" | jq -e . >/dev/null 2>&1; then + INTEGRATION_SUMMARY_JSON="null" +fi cat > "$OUTPUT_JSON" < "$OUTPUT_JSON" < "$OUTPUT_JSON" < --output [--git-commit ] [--git-branch ] [--gas-json ]" + echo "Usage: $0 --input-dir --output [--git-commit ] [--git-branch ] [--gas-json ] [--integration-summary ]" exit 1 fi @@ -28,6 +36,38 @@ format_s() { awk -v v="$1" 'BEGIN{printf "%.2f", v}'; } format_ms() { echo "$1 * 1000" | bc -l | awk '{printf "%.2f", $0}'; } format_kb() { echo "$1 / 1024" | bc -l | awk '{printf "%.2f", $0}'; } +hex_len_bytes() { + local hex="${1:-}" + python3 - "$hex" <<'PY' +import sys +h = sys.argv[1] or "" +if h.startswith("0x"): + h = h[2:] +if len(h) % 2 != 0: + print("0") +else: + print(len(h) // 2) +PY +} + +calldata_gas_from_hex() { + local hex="${1:-}" + python3 - "$hex" <<'PY' +import sys +h = sys.argv[1] or "" +if h.startswith("0x"): + h = h[2:] +if len(h) % 2 != 0: + print("0") + raise SystemExit(0) +gas = 0 +for i in range(0, len(h), 2): + b = h[i : i + 2] + gas += 4 if b == "00" else 16 +print(gas) +PY +} + find_json_by_path_fragment() { local frag="$1" for json_file in "$INPUT_DIR"/*.json; do @@ -113,25 +153,73 @@ artifact_metrics() { local name="$1" local label="$2" local verify_gas="$3" + local artifact_key="" + case "$name" in + Π_DKG) artifact_key="dkg" ;; + Π_dec) artifact_key="dec" ;; + esac if [ "$label" = "user_data_encryption" ]; then - local ct0 ct1 - ct0=$(find_json_by_path_fragment "/threshold/user_data_encryption_ct0") - ct1=$(find_json_by_path_fragment "/threshold/user_data_encryption_ct1") - if [ -z "$ct0" ] || [ -z "$ct1" ]; then - echo "| $name | N/A | N/A | $verify_gas | N/A | N/A |" >> "$OUTPUT_FILE" + local wrapper + wrapper=$(find_json_by_path_fragment "/threshold/user_data_encryption") + local proof_size public_size calldata total + + # Prefer the wrapper artifact when available; it matches what is posted/verified on-chain. + if [ -n "$wrapper" ]; then + proof_size=$(jq -r '.proof_generation.proof_size_bytes // 0' "$wrapper") + public_size=$(jq -r '.verification.public_inputs_size_bytes // 0' "$wrapper") + calldata=$(jq -r '.verification.calldata_gas_total // 0' "$wrapper") + total="N/A" + if [ "$verify_gas" != "N/A" ]; then total=$((verify_gas + calldata)); fi + echo "| $name | $(format_kb "$proof_size") KB | $(format_kb "$public_size") KB | $verify_gas | $calldata | $total |" >> "$OUTPUT_FILE" return fi - local proof_size public_size calldata total - proof_size=$(echo "$(jq -r '.proof_generation.proof_size_bytes // 0' "$ct0") + $(jq -r '.proof_generation.proof_size_bytes // 0' "$ct1")" | bc) - public_size=$(echo "$(jq -r '.verification.public_inputs_size_bytes // 0' "$ct0") + $(jq -r '.verification.public_inputs_size_bytes // 0' "$ct1")" | bc) - calldata=$(echo "$(jq -r '.verification.calldata_gas_total // 0' "$ct0") + $(jq -r '.verification.calldata_gas_total // 0' "$ct1")" | bc) - total="N/A" - if [ "$verify_gas" != "N/A" ]; then total=$((verify_gas + calldata)); fi - echo "| $name | $(format_kb "$proof_size") KB | $(format_kb "$public_size") KB | $verify_gas | $calldata | $total |" >> "$OUTPUT_FILE" + + echo "| $name | N/A | N/A | $verify_gas | N/A | N/A |" >> "$OUTPUT_FILE" return fi + # Prefer folded artifact sizes/calldata (when present) so table aligns with folded verify gas. + if [ -n "$artifact_key" ] && [ -f "$GAS_JSON" ]; then + local folded_proof_size folded_public_size folded_calldata + folded_proof_size=$(jq -r ".artifact_sizes_bytes.${artifact_key}.proof // empty" "$GAS_JSON") + folded_public_size=$(jq -r ".artifact_sizes_bytes.${artifact_key}.public_inputs // empty" "$GAS_JSON") + folded_calldata=$(jq -r ".calldata_gas.${artifact_key}.total // empty" "$GAS_JSON") + if [ -n "$folded_proof_size" ] && [ "$folded_proof_size" != "null" ] && [ "$folded_proof_size" != "0" ] \ + && [ -n "$folded_public_size" ] && [ "$folded_public_size" != "null" ] && [ "$folded_public_size" != "0" ] \ + && [ -n "$folded_calldata" ] && [ "$folded_calldata" != "null" ] && [ "$folded_calldata" != "0" ]; then + local folded_total="N/A" + if [ "$verify_gas" != "N/A" ]; then folded_total=$((verify_gas + folded_calldata)); fi + echo "| $name | $(format_kb "$folded_proof_size") KB | $(format_kb "$folded_public_size") KB | $verify_gas | $folded_calldata | $folded_total |" >> "$OUTPUT_FILE" + return + fi + fi + + # Sizes + calldata from integration summary folded hex (when gas JSON has no folded export). + if [ -n "$artifact_key" ] && [ -n "$INTEGRATION_SUMMARY_FILE" ] && [ -f "$INTEGRATION_SUMMARY_FILE" ]; then + local pfx ph pubh pb pubb cdp cdc folded_total + case "$artifact_key" in + dkg) pfx=".folded_artifacts.dkg_aggregator" ;; + dec) pfx=".folded_artifacts.decryption_aggregator" ;; + *) pfx="" ;; + esac + if [ -n "$pfx" ]; then + ph=$(jq -r "${pfx}.proof_hex // empty" "$INTEGRATION_SUMMARY_FILE" 2>/dev/null || true) + pubh=$(jq -r "${pfx}.public_inputs_hex // empty" "$INTEGRATION_SUMMARY_FILE" 2>/dev/null || true) + if [ -n "$ph" ] && [ "$ph" != "null" ] && [ -n "$pubh" ] && [ "$pubh" != "null" ]; then + pb=$(hex_len_bytes "$ph") + pubb=$(hex_len_bytes "$pubh") + cdp=$(calldata_gas_from_hex "$ph") + cdc=$(calldata_gas_from_hex "$pubh") + folded_calldata=$((cdp + cdc)) + folded_total="N/A" + if [ "$verify_gas" != "N/A" ]; then folded_total=$((verify_gas + folded_calldata)); fi + echo "| $name | $(format_kb "$pb") KB | $(format_kb "$pubb") KB | $verify_gas | $folded_calldata | $folded_total |" >> "$OUTPUT_FILE" + return + fi + fi + fi + local json_file json_file=$(find_json_by_path_fragment "$label") if [ -z "$json_file" ]; then @@ -170,7 +258,106 @@ sum_phase_metrics() { echo "$(format_s "$prove_sum") s|$(format_kb "$proof_sum") KB|$(format_kb "$bandwidth_sum") KB" } +integration_timing_seconds() { + local label="$1" + local val="" + local f + for f in "$INTEGRATION_SUMMARY_FILE" "$GAS_JSON"; do + [ -n "$f" ] && [ -f "$f" ] || continue + val=$(jq -r --arg label "$label" '.integration_summary.timings_seconds[]? | select(.label == $label) | .seconds' "$f" 2>/dev/null | head -1) + if [ -n "$val" ] && [ "$val" != "null" ]; then + echo "$val" + return + fi + val=$(jq -r --arg label "$label" '.timings_seconds[]? | select(.label == $label) | .seconds' "$f" 2>/dev/null | head -1) + if [ -n "$val" ] && [ "$val" != "null" ]; then + echo "$val" + return + fi + done + echo "" +} + +# Normalized integration summary object: either `results_*/integration_summary.json` or +# `crisp_verify_gas.json` → `.integration_summary` (see `BENCHMARK_SUMMARY_OUTPUT` in e3-tests). +integration_blob_from_inputs() { + local f blob + for f in "$INTEGRATION_SUMMARY_FILE" "$GAS_JSON"; do + [ -n "$f" ] && [ -f "$f" ] || continue + blob=$(jq -c 'if (.integration_summary != null) and (.integration_summary | type == "object") then .integration_summary elif has("integration_test") then . else empty end' "$f" 2>/dev/null || true) + if [ -n "$blob" ] && [ "$blob" != "null" ]; then + echo "$blob" + return 0 + fi + done + return 1 +} + +artifact_size_pair_from_gas() { + local key="$1" + local proof public bandwidth + if [ -f "$GAS_JSON" ]; then + proof=$(jq -r ".artifact_sizes_bytes.${key}.proof // empty" "$GAS_JSON" 2>/dev/null) + public=$(jq -r ".artifact_sizes_bytes.${key}.public_inputs // empty" "$GAS_JSON" 2>/dev/null) + if [ -n "$proof" ] && [ "$proof" != "null" ] && [ -n "$public" ] && [ "$public" != "null" ] \ + && [ "$proof" != "0" ] && [ "$public" != "0" ]; then + bandwidth=$(echo "$proof + $public" | bc) + echo "$(format_kb "$proof") KB|$(format_kb "$bandwidth") KB" + return + fi + fi + # Fallback: folded hex from integration summary export (test `BENCHMARK_SUMMARY_OUTPUT`). + if [ -n "$INTEGRATION_SUMMARY_FILE" ] && [ -f "$INTEGRATION_SUMMARY_FILE" ]; then + local pfx ph pubh + case "$key" in + dkg) pfx=".folded_artifacts.dkg_aggregator" ;; + dec) pfx=".folded_artifacts.decryption_aggregator" ;; + *) echo ""; return ;; + esac + ph=$(jq -r "${pfx}.proof_hex // empty" "$INTEGRATION_SUMMARY_FILE" 2>/dev/null || true) + pubh=$(jq -r "${pfx}.public_inputs_hex // empty" "$INTEGRATION_SUMMARY_FILE" 2>/dev/null || true) + if [ -n "$ph" ] && [ "$ph" != "null" ] && [ -n "$pubh" ] && [ "$pubh" != "null" ]; then + proof=$(hex_len_bytes "$ph") + public=$(hex_len_bytes "$pubh") + if [ "$proof" != "0" ] || [ "$public" != "0" ]; then + bandwidth=$(echo "$proof + $public" | bc) + echo "$(format_kb "$proof") KB|$(format_kb "$bandwidth") KB" + return + fi + fi + fi + echo "" +} + +load_protocol_params() { + local default_mod="${REPO_ROOT}/circuits/lib/src/configs/default/mod.nr" + local committee_name + committee_name=$(python3 - "$default_mod" <<'PY' +import re, sys +p = sys.argv[1] +try: + txt = open(p, "r", encoding="utf-8").read() +except Exception: + print("") + raise SystemExit(0) +m = re.search(r"committee::([a-zA-Z0-9_]+)::\{H,\s*N_PARTIES,\s*T\}", txt) +print(m.group(1) if m else "") +PY +) + [ -z "$committee_name" ] && committee_name="micro" + local committee_file="${REPO_ROOT}/circuits/lib/src/configs/committee/${committee_name}.nr" + local n t h + n=$(rg -N "N_PARTIES: u32 = " "$committee_file" | sed -E 's/.*= ([0-9]+);/\1/' | head -1) + t=$(rg -N "T: u32 = " "$committee_file" | sed -E 's/.*= ([0-9]+);/\1/' | head -1) + h=$(rg -N "H: u32 = " "$committee_file" | sed -E 's/.*= ([0-9]+);/\1/' | head -1) + [ -z "$n" ] && n="N/A" + [ -z "$t" ] && t="N/A" + [ -z "$h" ] && h="N/A" + echo "$h|$n|$t" +} + TIMESTAMP=$(date -u "+%Y-%m-%d %H:%M:%S UTC") +IFS='|' read -r PROTOCOL_H PROTOCOL_N PROTOCOL_T <<< "$(load_protocol_params)" cat > "$OUTPUT_FILE" < "$OUTPUT_FILE" < PublicKeyAggregated") +if [ -n "$p1_integration" ] && [ "$p1_integration" != "null" ]; then + p1t="$(format_s "$p1_integration") s" +fi +p4a_integration=$(integration_timing_seconds "Ciphertext published -> PlaintextAggregated") +if [ -n "$p4a_integration" ] && [ "$p4a_integration" != "null" ]; then + p4at="$(format_s "$p4a_integration") s" +fi + +# Keep role-phase rows aligned with artifact outputs when folded artifact sizes are available. +p2_artifact=$(artifact_size_pair_from_gas "dkg") +if [ -n "$p2_artifact" ]; then + IFS='|' read -r p2s p2b <<< "$p2_artifact" +fi +wrapper_json=$(find_json_by_path_fragment "/threshold/user_data_encryption") +if [ -n "$wrapper_json" ]; then + p3_proof_bytes=$(jq -r '.proof_generation.proof_size_bytes // 0' "$wrapper_json") + p3_public_bytes=$(jq -r '.verification.public_inputs_size_bytes // 0' "$wrapper_json") + p3_bandwidth_bytes=$(echo "$p3_proof_bytes + $p3_public_bytes" | bc) + p3s="$(format_kb "$p3_proof_bytes") KB" + p3b="$(format_kb "$p3_bandwidth_bytes") KB" +fi +p4a_artifact=$(artifact_size_pair_from_gas "dec") +if [ -n "$p4a_artifact" ]; then + IFS='|' read -r p4as p4ab <<< "$p4a_artifact" +fi + cat >> "$OUTPUT_FILE" <> "$OUTPUT_FILE" <> "$OUTPUT_FILE" + while IFS=$'\t' read -r label sec; do + [ -z "$label" ] && continue + echo "| $label | $(format_s "$sec") |" >> "$OUTPUT_FILE" + done < <(jq -r '.timings_seconds[]? | [.label, .seconds] | @tsv' <<<"$INTEGRATION_BLOB") + + if jq -e '.multithread != null' <<<"$INTEGRATION_BLOB" >/dev/null 2>&1; then + rt=$(jq -r '.multithread.rayon_threads' <<<"$INTEGRATION_BLOB") + mx=$(jq -r '.multithread.max_simultaneous_rayon_tasks' <<<"$INTEGRATION_BLOB") + cr=$(jq -r '.multithread.cores_available' <<<"$INTEGRATION_BLOB") + { + echo "" + echo "### Thread pool (same process as integration test)" + echo "" + echo "| Setting | Value |" + echo "|---------|-------|" + echo "| Rayon threads | $rt |" + echo "| Max simultaneous Rayon tasks | $mx |" + echo "| Cores available | $cr |" + } >> "$OUTPUT_FILE" + fi + + if jq -e '(.operation_timings | type == "array") and (.operation_timings | length > 0)' <<<"$INTEGRATION_BLOB" >/dev/null 2>&1; then + { + echo "" + echo "### CPU-bound operation timings (tracked in-process)" + echo "" + echo "| Name | Avg (s) | Runs | Total (s) |" + echo "|------|---------|------|-----------|" + } >> "$OUTPUT_FILE" + while IFS=$'\t' read -r name avgr runs tot; do + [ -z "$name" ] && continue + echo "| $name | $(format_s "$avgr") | $runs | $(format_s "$tot") |" >> "$OUTPUT_FILE" + done < <(jq -r '.operation_timings[]? | [.name, .avg_seconds, .runs, .total_seconds] | @tsv' <<<"$INTEGRATION_BLOB") + ott=$(jq -r '.operation_timings_total_seconds // empty' <<<"$INTEGRATION_BLOB") + if [ -n "$ott" ] && [ "$ott" != "null" ]; then + echo "" >> "$OUTPUT_FILE" + echo "Sum of tracked operation wall time: **$(format_s "$ott") s** (often much larger than end-to-end wall clock because work runs in parallel)." >> "$OUTPUT_FILE" + fi + fi +fi + +{ + echo "" + echo "## Raw circuit benchmark JSON (Nargo)" + echo "" +} >> "$OUTPUT_FILE" +shopt -s nullglob +raw_files=("$INPUT_DIR"/*.json) +if [ ${#raw_files[@]} -eq 0 ]; then + echo "_No \`.json\` files in this input directory._" >> "$OUTPUT_FILE" +else + echo "Source files for the **Circuit Benchmarks** table. Persist this directory with \`crisp_verify_gas.json\` (and optional \`integration_summary.json\`) to regenerate the report without re-running the integration test." >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "| File |" >> "$OUTPUT_FILE" + echo "|------|" >> "$OUTPUT_FILE" + for jf in "${raw_files[@]}"; do + echo "| \`$(basename "$jf")\` |" >> "$OUTPUT_FILE" + done +fi +shopt -u nullglob + first_json=$(ls "$INPUT_DIR"/*.json 2>/dev/null | head -1) if [ -n "$first_json" ]; then cpu_model=$(jq -r '.system_info.cpu_model // "unknown"' "$first_json") @@ -265,4 +555,11 @@ if [ -n "$first_json" ]; then EOF fi +cat >> "$OUTPUT_FILE" </dev/null || echo "unknown") +GIT_BRANCH=$(git -C "$REPO_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") +GAS_JSON="${OUTPUT_DIR}/crisp_verify_gas.json" +INTEGRATION_JSON="${OUTPUT_DIR}/integration_summary.json" + +GR=( "${SCRIPT_DIR}/generate_report.sh" + --input-dir "${OUTPUT_DIR}/raw" + --output "${OUTPUT_DIR}/report.md" + --git-commit "$GIT_COMMIT" + --git-branch "$GIT_BRANCH" + --gas-json "$GAS_JSON" +) +if [ -f "$INTEGRATION_JSON" ]; then + GR+=(--integration-summary "$INTEGRATION_JSON") +fi +"${GR[@]}" + +echo "✓ Report: ${OUTPUT_DIR}/report.md" diff --git a/circuits/benchmarks/scripts/replay_folded_verify_gas.sh b/circuits/benchmarks/scripts/replay_folded_verify_gas.sh new file mode 100755 index 000000000..4ff10956a --- /dev/null +++ b/circuits/benchmarks/scripts/replay_folded_verify_gas.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# Replay DkgAggregatorVerifier / DecryptionAggregatorVerifier estimateGas using folded proofs from an +# integration summary JSON (BENCHMARK_SUMMARY_OUTPUT shape: .folded_artifacts.{dkg_aggregator,...}) +# and merge verify_gas.dkg / verify_gas.dec into an existing crisp_verify_gas.json. +# +# Usage (from repo root): +# ./circuits/benchmarks/scripts/replay_folded_verify_gas.sh \ +# --summary /tmp/summary_secure.json \ +# --gas-json ./circuits/benchmarks/results_secure/crisp_verify_gas.json \ +# --build secure-8192 +# +# Use --build when Hardhat reverts with SumcheckFailed (verifier VKs must match the +# preset used to generate the folded proofs, e.g. secure-8192 for SecureThreshold8192). + +set -e + +SUMMARY_JSON="" +GAS_JSON="" +BUILD_PRESET="" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" +ENCLAVE_CONTRACTS="${REPO_ROOT}/packages/enclave-contracts" + +while [[ $# -gt 0 ]]; do + case $1 in + --summary) SUMMARY_JSON="$2"; shift 2 ;; + --gas-json) GAS_JSON="$2"; shift 2 ;; + --build) + BUILD_PRESET="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 --summary --gas-json [--build ]" + exit 1 + ;; + esac +done + +if [ -z "$SUMMARY_JSON" ] || [ -z "$GAS_JSON" ]; then + echo "Usage: $0 --summary --gas-json [--build ]" + exit 1 +fi +if [ ! -f "$SUMMARY_JSON" ]; then + echo "Error: summary file not found: $SUMMARY_JSON" + exit 1 +fi +if [ ! -f "$GAS_JSON" ]; then + echo "Error: gas JSON not found: $GAS_JSON" + exit 1 +fi + +if ! jq -e '.folded_artifacts.dkg_aggregator.proof_hex and .folded_artifacts.decryption_aggregator.proof_hex' "$SUMMARY_JSON" >/dev/null 2>&1; then + echo "Error: $SUMMARY_JSON must contain .folded_artifacts with dkg_aggregator and decryption_aggregator proof_hex" + exit 1 +fi + +RAW_DIR="$(cd "$(dirname "$GAS_JSON")" && pwd)/raw" +if [ ! -d "$RAW_DIR" ]; then + echo "Error: expected raw benchmark dir next to gas JSON: $RAW_DIR" + exit 1 +fi + +TMP_FOLDED="$(mktemp)" +TMP_GAS_PARTIAL="$(mktemp)" +trap 'rm -f "$TMP_FOLDED" "$TMP_GAS_PARTIAL"' EXIT + +jq -c '.folded_artifacts' "$SUMMARY_JSON" >"$TMP_FOLDED" + +if [ -n "$BUILD_PRESET" ]; then + echo " [replay-gas] Building verifier artifacts: pnpm build:circuits --preset ${BUILD_PRESET}" + (cd "$REPO_ROOT" && pnpm build:circuits --preset "$BUILD_PRESET") +fi + +echo " [replay-gas] Running Hardhat benchmarkGasFromRaw.ts (folded proofs)..." +( + cd "$ENCLAVE_CONTRACTS" && \ + BENCHMARK_RAW_DIR="$RAW_DIR" \ + BENCHMARK_GAS_OUTPUT="$TMP_GAS_PARTIAL" \ + BENCHMARK_FOLDED_JSON="$TMP_FOLDED" \ + pnpm hardhat run scripts/benchmarkGasFromRaw.ts --network hardhat +) + +if ! jq -e '.verify_gas.dkg and .verify_gas.dec' "$TMP_GAS_PARTIAL" >/dev/null 2>&1; then + echo "Error: partial gas output missing verify_gas.dkg/dec: $TMP_GAS_PARTIAL" + cat "$TMP_GAS_PARTIAL" + exit 1 +fi + +TMP_OUT="$(mktemp)" +jq --slurpfile patch "$TMP_GAS_PARTIAL" \ + '.verify_gas.dkg = $patch[0].verify_gas.dkg | .verify_gas.dec = $patch[0].verify_gas.dec' \ + "$GAS_JSON" >"$TMP_OUT" +mv "$TMP_OUT" "$GAS_JSON" +trap - EXIT +rm -f "$TMP_FOLDED" "$TMP_GAS_PARTIAL" + +echo " [replay-gas] Updated verify_gas.dkg and verify_gas.dec in: $GAS_JSON" +echo " [replay-gas] Regenerate the report with generate_report.sh (and --integration-summary if you still use it for timings)." diff --git a/circuits/benchmarks/scripts/run_benchmarks.sh b/circuits/benchmarks/scripts/run_benchmarks.sh index c7b32e772..84d1b219d 100755 --- a/circuits/benchmarks/scripts/run_benchmarks.sh +++ b/circuits/benchmarks/scripts/run_benchmarks.sh @@ -1,7 +1,7 @@ #!/bin/bash # run_benchmarks.sh - Main orchestration script for benchmarking circuits -# Usage: ./run_benchmarks.sh [--config ] [--mode insecure|secure] [--circuit ] [--skip-compile] [--clean] +# Usage: ./run_benchmarks.sh [--config ] [--mode insecure|secure] [--circuit ] [--skip-compile] [--clean] [--verbose] set -e @@ -12,6 +12,7 @@ CLEAN_ARTIFACTS=false MODE_OVERRIDE="" SKIP_COMPILE=false CIRCUIT_FILTER="" +VERBOSE=false # Parse arguments while [[ $# -gt 0 ]]; do @@ -40,9 +41,13 @@ while [[ $# -gt 0 ]]; do CLEAN_ARTIFACTS=true shift ;; + --verbose|-v) + VERBOSE=true + shift + ;; *) echo "Unknown option: $1" - echo "Usage: $0 [--config ] [--mode insecure|secure] [--circuit ] [--skip-compile] [--clean]" + echo "Usage: $0 [--config ] [--mode insecure|secure] [--circuit ] [--skip-compile] [--clean] [--verbose]" exit 1 ;; esac @@ -121,6 +126,9 @@ fi if [ "$SKIP_COMPILE" = true ]; then echo " Skip Compilation: Yes (using existing artifacts)" fi +if [ "$VERBOSE" = true ]; then + echo " Verbose Logging: Yes" +fi echo " Git Branch: $GIT_BRANCH" echo " Git Commit: $GIT_COMMIT" echo " Circuits: $(echo $CIRCUITS | wc -w | tr -d ' ')" @@ -129,6 +137,30 @@ echo " Base Directory: $CIRCUITS_BASE_DIR" echo " Output Directory: ${OUTPUT_DIR}" echo "" +# Preflight build for selected preset so raw benches and integration stages +# use consistent, freshly-generated circuit artifacts. +if [ "$SKIP_COMPILE" = false ]; then + if [ "$MODE" = "secure" ]; then + PRESET_NAME="secure-8192" + else + PRESET_NAME="insecure-512" + fi + echo "Preflight: pnpm build:circuits --preset ${PRESET_NAME}" + if [ "$VERBOSE" = true ]; then + ( + cd "$REPO_ROOT" && \ + pnpm build:circuits --preset "$PRESET_NAME" + ) + else + ( + cd "$REPO_ROOT" && \ + pnpm build:circuits --preset "$PRESET_NAME" >/dev/null + ) + fi + echo "Preflight build complete." + echo "" +fi + # Circuit-specific modes come from config.json (e.g. "config" has "modes": ["secure"]); see circuits/benchmarks/config.json RUN_CIRCUITS="" CIRCUIT_MODES=$(jq -r '.circuits[] | (if type == "string" then . else .name end) as $path | (if type == "object" and (.modes != null) then (.modes | join(",")) else "insecure,secure" end) | "\($path)\t\(.)"' "$CONFIG_FILE") @@ -212,18 +244,24 @@ echo "╔═══════════════════════ echo "║ Generating Report... ║" echo "╚════════════════════════════════════════════════╝" echo "" +echo "Stage 1/3: Running gas extraction pipeline (CRISP test + integration + EVM replay)..." # Try to retrieve verifier gas from the existing CRISP verify test path. GAS_JSON_FILE="${BENCHMARKS_DIR}/${OUTPUT_DIR}/crisp_verify_gas.json" # Remove any previous gas artifact so failures cannot leak stale values. rm -f "${GAS_JSON_FILE}" -if "${SCRIPT_DIR}/extract_crisp_verify_gas.sh" --output "${GAS_JSON_FILE}"; then +EXTRACT_ARGS=(--output "${GAS_JSON_FILE}" --mode "$MODE") +if [ "$VERBOSE" = true ]; then + EXTRACT_ARGS+=(--verbose) +fi +if "${SCRIPT_DIR}/extract_crisp_verify_gas.sh" "${EXTRACT_ARGS[@]}"; then echo "✓ CRISP verify gas extracted: ${GAS_JSON_FILE}" else echo "⚠️ Could not extract CRISP verify gas; report will show N/A for verify gas" fi # Generate markdown report +echo "Stage 2/3: Rendering markdown report from benchmarks + gas summary..." REPORT_FILE="${BENCHMARKS_DIR}/${OUTPUT_DIR}/report.md" "${SCRIPT_DIR}/generate_report.sh" \ --input-dir "${BENCHMARKS_DIR}/${OUTPUT_DIR}/raw" \ @@ -232,6 +270,13 @@ REPORT_FILE="${BENCHMARKS_DIR}/${OUTPUT_DIR}/report.md" --git-branch "$GIT_BRANCH" \ --gas-json "${GAS_JSON_FILE}" +INTEGRATION_SNAPSHOT="${BENCHMARKS_DIR}/${OUTPUT_DIR}/integration_summary.json" +if [ -f "${GAS_JSON_FILE}" ] && jq -e '.integration_summary != null' "${GAS_JSON_FILE}" >/dev/null 2>&1; then + jq '.integration_summary' "${GAS_JSON_FILE}" > "${INTEGRATION_SNAPSHOT}" + echo "✓ Wrote integration summary snapshot: ${INTEGRATION_SNAPSHOT}" +fi + +echo "Stage 3/3: Finalizing outputs..." echo "✓ Report generated: ${REPORT_FILE}" echo "" diff --git a/crates/keyshare/src/decryption_key_shared_collector.rs b/crates/keyshare/src/decryption_key_shared_collector.rs index a6253c587..ee294fe58 100644 --- a/crates/keyshare/src/decryption_key_shared_collector.rs +++ b/crates/keyshare/src/decryption_key_shared_collector.rs @@ -17,6 +17,17 @@ use tracing::{info, warn}; use crate::ThresholdKeyshare; const DEFAULT_COLLECTION_TIMEOUT: Duration = Duration::from_secs(3600); +const COLLECTION_TIMEOUT_ENV: &str = "E3_DECRYPTION_KEY_SHARED_COLLECTION_TIMEOUT_SECS"; + +fn collection_timeout() -> Duration { + match std::env::var(COLLECTION_TIMEOUT_ENV) + .ok() + .and_then(|v| v.parse::().ok()) + { + Some(0) | None => DEFAULT_COLLECTION_TIMEOUT, + Some(secs) => Duration::from_secs(secs), + } +} enum CollectorState { Collecting, @@ -91,16 +102,14 @@ impl Actor for DecryptionKeySharedCollector { fn started(&mut self, ctx: &mut Self::Context) { ctx.set_mailbox_capacity(MAILBOX_LIMIT); + let timeout = collection_timeout(); info!( e3_id = %self.e3_id, "DecryptionKeySharedCollector started, expecting {} parties, timeout {:?}", self.expected.len(), - DEFAULT_COLLECTION_TIMEOUT - ); - let handle = ctx.notify_later( - DecryptionKeySharedCollectionTimeout, - DEFAULT_COLLECTION_TIMEOUT, + timeout ); + let handle = ctx.notify_later(DecryptionKeySharedCollectionTimeout, timeout); self.timeout_handle = Some(handle); } } diff --git a/crates/keyshare/src/encryption_key_collector.rs b/crates/keyshare/src/encryption_key_collector.rs index 184ad96a9..f0843c837 100644 --- a/crates/keyshare/src/encryption_key_collector.rs +++ b/crates/keyshare/src/encryption_key_collector.rs @@ -20,6 +20,17 @@ use e3_utils::MAILBOX_LIMIT; use tracing::{info, warn}; const DEFAULT_COLLECTION_TIMEOUT: Duration = Duration::from_secs(600); +const COLLECTION_TIMEOUT_ENV: &str = "E3_ENCRYPTION_KEY_COLLECTION_TIMEOUT_SECS"; + +fn collection_timeout() -> Duration { + match std::env::var(COLLECTION_TIMEOUT_ENV) + .ok() + .and_then(|v| v.parse::().ok()) + { + Some(0) | None => DEFAULT_COLLECTION_TIMEOUT, + Some(secs) => Duration::from_secs(secs), + } +} use crate::ThresholdKeyshare; @@ -101,13 +112,14 @@ impl Actor for EncryptionKeyCollector { fn started(&mut self, ctx: &mut Self::Context) { ctx.set_mailbox_capacity(MAILBOX_LIMIT); + let timeout = collection_timeout(); info!( e3_id = %self.e3_id, "EncryptionKeyCollector started, scheduling timeout in {:?}", - DEFAULT_COLLECTION_TIMEOUT + timeout ); - let handle = ctx.notify_later(EncryptionKeyCollectionTimeout, DEFAULT_COLLECTION_TIMEOUT); + let handle = ctx.notify_later(EncryptionKeyCollectionTimeout, timeout); self.timeout_handle = Some(handle); } } diff --git a/crates/keyshare/src/threshold_share_collector.rs b/crates/keyshare/src/threshold_share_collector.rs index 4c7e65e9c..c3085c594 100644 --- a/crates/keyshare/src/threshold_share_collector.rs +++ b/crates/keyshare/src/threshold_share_collector.rs @@ -35,6 +35,17 @@ pub struct ReceivedShareProofs { } const DEFAULT_COLLECTION_TIMEOUT: Duration = Duration::from_secs(3600); +const COLLECTION_TIMEOUT_ENV: &str = "E3_THRESHOLD_SHARE_COLLECTION_TIMEOUT_SECS"; + +fn collection_timeout() -> Duration { + match std::env::var(COLLECTION_TIMEOUT_ENV) + .ok() + .and_then(|v| v.parse::().ok()) + { + Some(0) | None => DEFAULT_COLLECTION_TIMEOUT, + Some(secs) => Duration::from_secs(secs), + } +} pub(crate) enum CollectorState { Collecting, @@ -93,13 +104,14 @@ impl Actor for ThresholdShareCollector { fn started(&mut self, ctx: &mut Self::Context) { ctx.set_mailbox_capacity(MAILBOX_LIMIT); + let timeout = collection_timeout(); info!( e3_id = %self.e3_id, "ThresholdShareCollector started, scheduling timeout in {:?}", - DEFAULT_COLLECTION_TIMEOUT + timeout ); // Schedule timeout - let handle = ctx.notify_later(ThresholdShareCollectionTimeout, DEFAULT_COLLECTION_TIMEOUT); + let handle = ctx.notify_later(ThresholdShareCollectionTimeout, timeout); self.timeout_handle = Some(handle); } } diff --git a/crates/multithread/src/report.rs b/crates/multithread/src/report.rs index da9a05def..ac44e734c 100644 --- a/crates/multithread/src/report.rs +++ b/crates/multithread/src/report.rs @@ -113,6 +113,15 @@ impl Handler for MultithreadReport { } } +/// One row of the flattened multithread report (seconds, for export / dashboards). +#[derive(Debug, Clone, PartialEq)] +pub struct OperationTimingSec { + pub name: String, + pub avg_seconds: f64, + pub runs: u64, + pub total_seconds: f64, +} + #[derive(MessageResponse, Debug, Clone, Eq, PartialEq)] pub struct FlattenedReport { cores_available: usize, @@ -124,6 +133,45 @@ pub struct FlattenedReport { runs: HashMap, } +impl FlattenedReport { + pub fn rayon_threads(&self) -> usize { + self.rayon_threads + } + + pub fn max_simultaneous_rayon_tasks(&self) -> usize { + self.max_simultaneous_rayon_tasks + } + + pub fn cores_available(&self) -> usize { + self.cores_available + } + + /// Wall-clock sum of all tracked operation durations (same as printed "Total time"). + pub fn tracked_total_seconds(&self) -> f64 { + self.mt_total.as_secs_f64() + } + + /// Per-operation averages and totals, sorted by name (stable with `Display` output). + pub fn operation_timings_sec(&self) -> Vec { + let mut names: Vec<_> = self.avg_dur.keys().cloned().collect(); + names.sort(); + names + .into_iter() + .map(|name| { + let runs = *self.runs.get(&name).unwrap_or(&0); + let total = *self.total_dur.get(&name).unwrap_or(&Duration::ZERO); + let avg = *self.avg_dur.get(&name).unwrap_or(&Duration::ZERO); + OperationTimingSec { + name, + avg_seconds: avg.as_secs_f64(), + runs, + total_seconds: total.as_secs_f64(), + } + }) + .collect() + } +} + impl std::fmt::Display for FlattenedReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "{:<32} {:>5}", "Rayon Threads:", self.rayon_threads)?; diff --git a/crates/tests/tests/integration.rs b/crates/tests/tests/integration.rs index 7bac03840..1378265e9 100644 --- a/crates/tests/tests/integration.rs +++ b/crates/tests/tests/integration.rs @@ -48,6 +48,7 @@ use num_bigint::BigUint; use rand::rngs::OsRng; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; +use std::ffi::OsString; use std::time::{Duration, Instant}; use std::{fs, path::PathBuf, sync::Arc}; use tokio::{ @@ -55,10 +56,111 @@ use tokio::{ time::sleep, }; +#[derive(Debug, Clone, Copy)] +struct BenchmarkParams { + /// Noir artifact preset directory name under `circuits/bin/` (e.g. `secure-8192`). + preset_subdir: &'static str, + /// BFV parameter family used for BFV/trBFV computations. + bfv_preset: BfvPreset, + /// Statistical security parameter λ used for smudging bound / error_size. + lambda: usize, + /// Collector-timeout env var bundle for secure runs. + collection_timeout_secs: Option<(u64, u64, u64)>, + /// Expected upper-bounds for history collection (end-to-end wall clock). + pubkey_flow_timeout: Duration, + plaintext_flow_timeout: Duration, +} + +fn select_benchmark_params() -> BenchmarkParams { + let benchmark_mode = std::env::var("BENCHMARK_MODE").unwrap_or_else(|_| "insecure".to_string()); + let is_secure_mode = benchmark_mode == "secure"; + + let bfv_preset = if is_secure_mode { + BfvPreset::SecureThreshold8192 + } else { + DEFAULT_BFV_PRESET + }; + + // λ is part of the preset metadata; using a hard-coded value here will mix parameter + // families and can invalidate noise/security assumptions. + let lambda = bfv_preset.metadata().lambda; + + let preset_subdir = if is_secure_mode { + "secure-8192" + } else { + "insecure-512" + }; + + let collection_timeout_secs = if is_secure_mode { + Some((1800, 7200, 7200)) + } else { + None + }; + + let pubkey_flow_timeout = if is_secure_mode { + Duration::from_secs(15_000) + } else { + Duration::from_secs(5_000) + }; + let plaintext_flow_timeout = if is_secure_mode { + Duration::from_secs(3_000) + } else { + Duration::from_secs(1_000) + }; + + BenchmarkParams { + preset_subdir, + bfv_preset, + lambda, + collection_timeout_secs, + pubkey_flow_timeout, + plaintext_flow_timeout, + } +} + +/// RAII guard that restores the benchmark-specific collector-timeout env vars on scope exit. +/// This prevents leaking secure-mode tuning into other tests/processes. +struct EnvTimeoutVarsGuard { + enc: Option, + thr: Option, + dec_shared: Option, +} + +impl EnvTimeoutVarsGuard { + fn new() -> Self { + Self { + enc: std::env::var_os("E3_ENCRYPTION_KEY_COLLECTION_TIMEOUT_SECS"), + thr: std::env::var_os("E3_THRESHOLD_SHARE_COLLECTION_TIMEOUT_SECS"), + dec_shared: std::env::var_os("E3_DECRYPTION_KEY_SHARED_COLLECTION_TIMEOUT_SECS"), + } + } +} + +impl Drop for EnvTimeoutVarsGuard { + fn drop(&mut self) { + fn restore(name: &str, original: &Option) { + if let Some(v) = original { + std::env::set_var(name, v); + } else { + std::env::remove_var(name); + } + } + + restore("E3_ENCRYPTION_KEY_COLLECTION_TIMEOUT_SECS", &self.enc); + restore("E3_THRESHOLD_SHARE_COLLECTION_TIMEOUT_SECS", &self.thr); + restore( + "E3_DECRYPTION_KEY_SHARED_COLLECTION_TIMEOUT_SECS", + &self.dec_shared, + ); + } +} + /// Create a ZkBackend for integration tests. /// If a local bb binary is found, uses it with fixture files (fast path). /// Otherwise, calls `ensure_installed()` to download bb + circuits (CI path). -async fn setup_test_zk_backend() -> Result<(ZkBackend, tempfile::TempDir)> { +async fn setup_test_zk_backend( + preset_subdir: &'static str, +) -> Result<(ZkBackend, tempfile::TempDir)> { let temp = get_tempdir().unwrap(); let temp_path = temp.path(); let noir_dir = temp_path.join("noir"); @@ -168,8 +270,7 @@ async fn setup_test_zk_backend() -> Result<(ZkBackend, tempfile::TempDir)> { } // ── recursive/ variant (inner/base proofs, uses .vk_noir) ────────── - // Tests use insecure params, so fixtures go under insecure-512/ - let preset_dir = circuits_dir.join("insecure-512"); + let preset_dir = circuits_dir.join(preset_subdir); let rv = preset_dir.join("recursive"); @@ -758,6 +859,18 @@ fn repeat(ch: char, num: usize) -> String { s } +fn to_hex(bytes: &[u8]) -> String { + let mut out = String::from("0x"); + for b in bytes { + out.push_str(&format!("{:02x}", b)); + } + out +} + +fn json_escape(s: &str) -> String { + s.replace('\\', "\\\\").replace('"', "\\\"") +} + impl Report { pub fn push(&mut self, repo: (&str, Duration)) { let (label, dur) = repo; @@ -826,8 +939,25 @@ async fn test_trbfv_actor() -> Result<()> { let system = EventSystem::new().with_fresh_bus(); let bus = system.handle()?.enable("test"); - // Parameters (128bits of security) - let params_raw = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); + // Parameters selected by benchmark mode. + let benchmark_params = select_benchmark_params(); + let _env_guard = EnvTimeoutVarsGuard::new(); + if let Some((enc, threshold, dec_shared)) = benchmark_params.collection_timeout_secs { + std::env::set_var("E3_ENCRYPTION_KEY_COLLECTION_TIMEOUT_SECS", enc.to_string()); + std::env::set_var( + "E3_THRESHOLD_SHARE_COLLECTION_TIMEOUT_SECS", + threshold.to_string(), + ); + std::env::set_var( + "E3_DECRYPTION_KEY_SHARED_COLLECTION_TIMEOUT_SECS", + dec_shared.to_string(), + ); + } + + let pubkey_flow_timeout = benchmark_params.pubkey_flow_timeout; + let plaintext_flow_timeout = benchmark_params.plaintext_flow_timeout; + + let params_raw = BfvParamSet::from(benchmark_params.bfv_preset).build_arc(); // Encoded Params let params = ArcBytes::from_bytes(&encode_bfv_params(¶ms_raw.clone())); @@ -837,11 +967,9 @@ async fn test_trbfv_actor() -> Result<()> { let threshold_n = 3; let esi_per_ct = 1; - // WARNING: INSECURE SECURITY PARAMETER LAMBDA. - // This is just for INSECURE parameter set. - // This is not secure and should not be used in production. - // For production use lambda = 80. - let lambda = 2; + // Statistical security parameter λ used for smudging bound / error_size. + // Comes from the selected BFV preset metadata to avoid mixing parameter families. + let lambda = benchmark_params.lambda; let seed = create_seed_from_u64(123); let error_size = ArcBytes::from_bytes(&BigUint::to_bytes_be(&calculate_error_size( @@ -862,7 +990,7 @@ async fn test_trbfv_actor() -> Result<()> { let multithread_report = MultithreadReport::new(max_threadroom, concurrent_jobs).start(); // Setup ZK backend for proof generation/verification - let (zk_backend, _zk_temp) = setup_test_zk_backend().await?; + let (zk_backend, _zk_temp) = setup_test_zk_backend(benchmark_params.preset_subdir).await?; let nodes = CiphernodeSystemBuilder::new() // All nodes run the same binary under the aggregator-committee model. @@ -946,7 +1074,7 @@ async fn test_trbfv_actor() -> Result<()> { // // - m=1. // - n=3 - // - lambda=2 + // - lambda -> calculate_error_size uses the selected BFV preset metadata // - error_size -> calculate using calculate_error_size // - esi_per_ciphertext = 1 /////////////////////////////////////////////////////////////////////////////////// @@ -965,7 +1093,7 @@ async fn test_trbfv_actor() -> Result<()> { seed: seed.clone(), error_size, esi_per_ct: esi_per_ct as usize, - params_preset: DEFAULT_BFV_PRESET, + params_preset: benchmark_params.bfv_preset, params, proof_aggregation_enabled, }; @@ -1052,8 +1180,8 @@ async fn test_trbfv_actor() -> Result<()> { .take_history_with_timeouts( 0, expected_events.len(), - Some(Duration::from_secs(5000)), - Some(Duration::from_secs(5000)), + Some(pubkey_flow_timeout), + Some(pubkey_flow_timeout), ) .await .map_err(|e| anyhow::anyhow!("FAILURE on node 0: {expected_events:?} : {e}"))?; @@ -1203,14 +1331,19 @@ async fn test_trbfv_actor() -> Result<()> { expected_events.extend_from_slice(&DS3); expected_events.push("PlaintextAggregated"); + println!( + "[bench-progress] waiting for PlaintextAggregated flow on observer node (expected events: {})", + expected_events.len() + ); let h = expect_node_events_with_timeouts( &nodes, 0, &expected_events, - Duration::from_secs(1000), - Duration::from_secs(1000), + plaintext_flow_timeout, + plaintext_flow_timeout, ) .await?; + println!("[bench-progress] PlaintextAggregated observed on collector path"); let active_aggregator_history = nodes.get_history(active_aggregator_index).await?; const C6_VERIFY_PREFIX: [&str; 19] = [ @@ -1340,13 +1473,6 @@ async fn test_trbfv_actor() -> Result<()> { dkg_aggregator_proof.as_ref(), decryption_aggregator_proofs.first(), ) { - fn to_hex(bytes: &[u8]) -> String { - let mut out = String::from("0x"); - for b in bytes { - out.push_str(&format!("{:02x}", b)); - } - out - } let json = format!( concat!( "{{\n", @@ -1404,6 +1530,91 @@ async fn test_trbfv_actor() -> Result<()> { println!("{}", mt_report); report.push(("Entire Test", whole_test.elapsed())); + if let Ok(path) = std::env::var("BENCHMARK_SUMMARY_OUTPUT") { + let operation_timings_json = mt_report + .operation_timings_sec() + .iter() + .map(|op| { + format!( + " {{\"name\": \"{}\", \"avg_seconds\": {:.9}, \"runs\": {}, \"total_seconds\": {:.9}}}", + json_escape(&op.name), + op.avg_seconds, + op.runs, + op.total_seconds + ) + }) + .collect::>() + .join(",\n"); + + let timings_json = report + .inner + .iter() + .map(|(label, duration)| { + format!( + " {{\"label\": \"{}\", \"seconds\": {:.9}}}", + json_escape(label), + duration.as_secs_f64() + ) + }) + .collect::>() + .join(",\n"); + + let folded_section = if let (Some(dkg_proof), Some(dec_proof)) = ( + dkg_aggregator_proof.as_ref(), + decryption_aggregator_proofs.first(), + ) { + format!( + concat!( + " \"folded_artifacts\": {{\n", + " \"dkg_aggregator\": {{\n", + " \"proof_hex\": \"{}\",\n", + " \"public_inputs_hex\": \"{}\"\n", + " }},\n", + " \"decryption_aggregator\": {{\n", + " \"proof_hex\": \"{}\",\n", + " \"public_inputs_hex\": \"{}\"\n", + " }}\n", + " }}\n" + ), + to_hex(&dkg_proof.data), + to_hex(&dkg_proof.public_signals), + to_hex(&dec_proof.data), + to_hex(&dec_proof.public_signals), + ) + } else { + String::from(" \"folded_artifacts\": null\n") + }; + + let summary_json = format!( + concat!( + "{{\n", + " \"integration_test\": \"test_trbfv_actor\",\n", + " \"multithread\": {{\n", + " \"rayon_threads\": {},\n", + " \"max_simultaneous_rayon_tasks\": {},\n", + " \"cores_available\": {}\n", + " }},\n", + " \"operation_timings\": [\n", + "{}\n", + " ],\n", + " \"operation_timings_total_seconds\": {:.9},\n", + " \"timings_seconds\": [\n", + "{}\n", + " ],\n", + "{}", + "}}\n" + ), + mt_report.rayon_threads(), + mt_report.max_simultaneous_rayon_tasks(), + mt_report.cores_available(), + operation_timings_json, + mt_report.tracked_total_seconds(), + timings_json, + folded_section + ); + fs::write(&path, summary_json)?; + println!("Wrote benchmark summary to {path}"); + } println!("{}", report.serialize()); Ok(()) @@ -1628,7 +1839,8 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { Ok(result) } - let (zk_backend, _zk_temp) = setup_test_zk_backend().await?; + let (zk_backend, _zk_temp) = + setup_test_zk_backend(select_benchmark_params().preset_subdir).await?; let e3_id = E3id::new("1234", 1); let (rng, cn1_address, cn1_data, cn2_address, cn2_data, cipher, history, params, crpoly) = { @@ -1883,7 +2095,8 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { // Setup let (bus, rng, seed, params, crpoly, _, _) = get_common_setup(None)?; let cipher = Arc::new(Cipher::from_password("Don't tell anyone my secret").await?); - let (zk_backend, _zk_temp) = setup_test_zk_backend().await?; + let (zk_backend, _zk_temp) = + setup_test_zk_backend(select_benchmark_params().preset_subdir).await?; // Setup actual ciphernodes and dispatch add events let ciphernodes = create_local_ciphernodes(&bus, &rng, 3, &cipher, zk_backend.clone()).await?;