From 7df3cad298ea4d0194af1dcea8afc397a7c0540e Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 18 May 2026 14:58:11 +0200 Subject: [PATCH 1/5] bind circuits of proof agg to vk hashes --- .../test/RevertOnVerifyCircuitVerifier.sol | 18 +++ .../verifiers/bfv/BfvDecryptionVerifier.sol | 20 +++- .../contracts/verifiers/bfv/BfvPkVerifier.sol | 22 +++- .../ignition/modules/bfvDecryptionVerifier.ts | 13 ++ .../ignition/modules/bfvPkVerifier.ts | 17 ++- .../scripts/benchmarkGasFromRaw.ts | 4 +- .../deployAndSave/bfvDecryptionVerifier.ts | 16 ++- .../scripts/deployAndSave/bfvPkVerifier.ts | 16 ++- packages/enclave-contracts/scripts/utils.ts | 52 ++++++++ .../test/BfvDecryptionVerifier.spec.ts | 99 +++++++++++++++- .../test/BfvPkVerifier.spec.ts | 111 +++++++++++++++--- 11 files changed, 361 insertions(+), 27 deletions(-) create mode 100644 packages/enclave-contracts/contracts/test/RevertOnVerifyCircuitVerifier.sol diff --git a/packages/enclave-contracts/contracts/test/RevertOnVerifyCircuitVerifier.sol b/packages/enclave-contracts/contracts/test/RevertOnVerifyCircuitVerifier.sol new file mode 100644 index 0000000000..7679ed838a --- /dev/null +++ b/packages/enclave-contracts/contracts/test/RevertOnVerifyCircuitVerifier.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +pragma solidity 0.8.28; + +import { ICircuitVerifier } from "../interfaces/ICircuitVerifier.sol"; + +/// @notice Test helper: reverts if `verify` is invoked (proves early return in wrappers). +contract RevertOnVerifyCircuitVerifier is ICircuitVerifier { + function verify( + bytes calldata, + bytes32[] calldata + ) external pure returns (bool) { + revert("verify called"); + } +} diff --git a/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol b/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol index 7b9ee93640..91b7c5c7d3 100644 --- a/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol +++ b/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol @@ -26,8 +26,20 @@ contract BfvDecryptionVerifier is IDecryptionVerifier { /// @notice Underlying Honk verifier for the DecryptionAggregator circuit. ICircuitVerifier public immutable circuitVerifier; - constructor(address _circuitVerifier) { + /// @notice Expected recursive VK hash for the c6_fold sub-circuit (`publicInputs[0]`). + bytes32 public immutable expectedC6FoldKeyHash; + + /// @notice Expected recursive VK hash for the C7/decrypted_shares_aggregation sub-circuit (`publicInputs[1]`). + bytes32 public immutable expectedC7KeyHash; + + constructor( + address _circuitVerifier, + bytes32 _expectedC6FoldKeyHash, + bytes32 _expectedC7KeyHash + ) { circuitVerifier = ICircuitVerifier(_circuitVerifier); + expectedC6FoldKeyHash = _expectedC6FoldKeyHash; + expectedC7KeyHash = _expectedC7KeyHash; } /// @inheritdoc IDecryptionVerifier @@ -43,6 +55,12 @@ contract BfvDecryptionVerifier is IDecryptionVerifier { if (publicInputs.length < MESSAGE_COEFFS_COUNT) { return false; } + if (publicInputs[0] != expectedC6FoldKeyHash) { + return false; + } + if (publicInputs[1] != expectedC7KeyHash) { + return false; + } if (!_verifyPlaintextHash(publicInputs, plaintextOutputHash)) { return false; } diff --git a/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol b/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol index 584edc2237..44c1c11832 100644 --- a/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol +++ b/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol @@ -21,8 +21,20 @@ contract BfvPkVerifier is IPkVerifier { /// @notice Underlying Honk verifier for the DkgAggregator circuit. ICircuitVerifier public immutable circuitVerifier; - constructor(address _circuitVerifier) { + /// @notice Expected recursive VK hash for the nodes_fold sub-circuit (`publicInputs[0]`). + bytes32 public immutable expectedNodesFoldKeyHash; + + /// @notice Expected recursive VK hash for the C5/pk_aggregation sub-circuit (`publicInputs[1]`). + bytes32 public immutable expectedC5KeyHash; + + constructor( + address _circuitVerifier, + bytes32 _expectedNodesFoldKeyHash, + bytes32 _expectedC5KeyHash + ) { circuitVerifier = ICircuitVerifier(_circuitVerifier); + expectedNodesFoldKeyHash = _expectedNodesFoldKeyHash; + expectedC5KeyHash = _expectedC5KeyHash; } /// @inheritdoc IPkVerifier @@ -35,7 +47,13 @@ contract BfvPkVerifier is IPkVerifier { (bytes, bytes32[]) ); - if (publicInputs.length == 0) { + if (publicInputs.length < 2) { + return false; + } + if (publicInputs[0] != expectedNodesFoldKeyHash) { + return false; + } + if (publicInputs[1] != expectedC5KeyHash) { return false; } if (publicInputs[publicInputs.length - 1] != pkCommitment) { diff --git a/packages/enclave-contracts/ignition/modules/bfvDecryptionVerifier.ts b/packages/enclave-contracts/ignition/modules/bfvDecryptionVerifier.ts index 964c9e324e..3ce4e43d7a 100644 --- a/packages/enclave-contracts/ignition/modules/bfvDecryptionVerifier.ts +++ b/packages/enclave-contracts/ignition/modules/bfvDecryptionVerifier.ts @@ -5,6 +5,10 @@ // or FITNESS FOR A PARTICULAR PURPOSE. import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS, + readVkRecursiveHash, +} from "../../scripts/utils"; import decryptionAggregatorVerifierModule from "./decryptionAggregatorVerifier"; export default buildModule("BfvDecryptionVerifier", (m) => { @@ -12,8 +16,17 @@ export default buildModule("BfvDecryptionVerifier", (m) => { decryptionAggregatorVerifierModule, ); + const expectedC6FoldKeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7KeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + const bfvDecryptionVerifier = m.contract("BfvDecryptionVerifier", [ decryptionAggregatorVerifier, + expectedC6FoldKeyHash, + expectedC7KeyHash, ]); return { bfvDecryptionVerifier }; diff --git a/packages/enclave-contracts/ignition/modules/bfvPkVerifier.ts b/packages/enclave-contracts/ignition/modules/bfvPkVerifier.ts index afc635b170..be7a632926 100644 --- a/packages/enclave-contracts/ignition/modules/bfvPkVerifier.ts +++ b/packages/enclave-contracts/ignition/modules/bfvPkVerifier.ts @@ -5,12 +5,27 @@ // or FITNESS FOR A PARTICULAR PURPOSE. import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS, + readVkRecursiveHash, +} from "../../scripts/utils"; import dkgAggregatorVerifierModule from "./dkgAggregatorVerifier"; export default buildModule("BfvPkVerifier", (m) => { const { dkgAggregatorVerifier } = m.useModule(dkgAggregatorVerifierModule); - const bfvPkVerifier = m.contract("BfvPkVerifier", [dkgAggregatorVerifier]); + const expectedNodesFoldKeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + + const bfvPkVerifier = m.contract("BfvPkVerifier", [ + dkgAggregatorVerifier, + expectedNodesFoldKeyHash, + expectedC5KeyHash, + ]); return { bfvPkVerifier }; }) as any; diff --git a/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts b/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts index 1e42b1032f..710d72b43c 100644 --- a/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts +++ b/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts @@ -129,7 +129,7 @@ async function main() { const bfvPk = await ( await ethers.getContractFactory("BfvPkVerifier") - ).deploy(dkgAggAddress); + ).deploy(dkgAggAddress, dkgPublicInputs[0], dkgPublicInputs[1]); await bfvPk.waitForDeployment(); const dkgEncodedProof = abiCoder.encode( @@ -141,7 +141,7 @@ async function main() { const bfvDec = await ( await ethers.getContractFactory("BfvDecryptionVerifier") - ).deploy(decAggAddress); + ).deploy(decAggAddress, decPublicInputs[0], decPublicInputs[1]); await bfvDec.waitForDeployment(); const decEncodedProof = abiCoder.encode( diff --git a/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts b/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts index 8cd9687708..ef22900ecf 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts @@ -9,7 +9,12 @@ import { BfvDecryptionVerifier, BfvDecryptionVerifier__factory as BfvDecryptionVerifierFactory, } from "../../types"; -import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; +import { + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS, + readDeploymentArgs, + readVkRecursiveHash, + storeDeploymentArgs, +} from "../utils"; export const deployAndSaveBfvDecryptionVerifier = async ( hre: HardhatRuntimeEnvironment, @@ -43,11 +48,20 @@ export const deployAndSaveBfvDecryptionVerifier = async ( return { bfvDecryptionVerifier }; } + const expectedC6FoldKeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7KeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + const bfvDecryptionVerifierFactory = await ethers.getContractFactory( "BfvDecryptionVerifier", ); const bfvDecryptionVerifier = await bfvDecryptionVerifierFactory.deploy( circuitVerifierArgs.address, + expectedC6FoldKeyHash, + expectedC7KeyHash, ); await bfvDecryptionVerifier.waitForDeployment(); diff --git a/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts b/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts index e47245c7e8..d2eaacdb76 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts @@ -9,7 +9,12 @@ import { BfvPkVerifier, BfvPkVerifier__factory as BfvPkVerifierFactory, } from "../../types"; -import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; +import { + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS, + readDeploymentArgs, + readVkRecursiveHash, + storeDeploymentArgs, +} from "../utils"; export const deployAndSaveBfvPkVerifier = async ( hre: HardhatRuntimeEnvironment, @@ -41,9 +46,18 @@ export const deployAndSaveBfvPkVerifier = async ( return { bfvPkVerifier }; } + const expectedNodesFoldKeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + const bfvPkVerifierFactory = await ethers.getContractFactory("BfvPkVerifier"); const bfvPkVerifier = await bfvPkVerifierFactory.deploy( circuitVerifierArgs.address, + expectedNodesFoldKeyHash, + expectedC5KeyHash, ); await bfvPkVerifier.waitForDeployment(); diff --git a/packages/enclave-contracts/scripts/utils.ts b/packages/enclave-contracts/scripts/utils.ts index bd1eeaf2b5..324ac681b9 100644 --- a/packages/enclave-contracts/scripts/utils.ts +++ b/packages/enclave-contracts/scripts/utils.ts @@ -4,10 +4,62 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. import fs from "fs"; +import { fileURLToPath } from "node:url"; import path from "path"; export const deploymentsFile = path.join("deployed_contracts.json"); +/** Monorepo root (`enclave/`), resolved from `packages/enclave-contracts/scripts/`. */ +export const REPO_ROOT = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + "../../..", +); + +/** Recursive VK hashes for `BfvPkVerifier` sub-circuits (from `pnpm compile:circuits`). */ +export const BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS = { + nodesFold: path.join( + REPO_ROOT, + "circuits/bin/recursive_aggregation/nodes_fold/target/nodes_fold.vk_recursive_hash", + ), + c5: path.join( + REPO_ROOT, + "circuits/bin/threshold/target/pk_aggregation.vk_recursive_hash", + ), +} as const; + +/** Recursive VK hashes for `BfvDecryptionVerifier` sub-circuits (from `pnpm compile:circuits`). */ +export const BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS = { + c6Fold: path.join( + REPO_ROOT, + "circuits/bin/recursive_aggregation/c6_fold/target/c6_fold.vk_recursive_hash", + ), + c7: path.join( + REPO_ROOT, + "circuits/bin/threshold/target/decrypted_shares_aggregation.vk_recursive_hash", + ), +} as const; + +/** + * Reads a 32-byte recursive VK hash emitted by the circuit build (`*.vk_recursive_hash`). + * Co-redeploy `BfvPkVerifier` / `BfvDecryptionVerifier` when the corresponding sub-circuit VK changes. + */ +export function readVkRecursiveHash(filePath: string): string { + if (!fs.existsSync(filePath)) { + throw new Error( + `Missing circuit VK hash file: ${filePath}. Run pnpm compile:circuits.`, + ); + } + + const raw = fs.readFileSync(filePath); + if (raw.length !== 32) { + throw new Error( + `Invalid VK hash length in ${filePath}: expected 32 bytes, got ${raw.length}`, + ); + } + + return `0x${raw.toString("hex")}`; +} + // Type for deployment arguments export interface DeploymentArgs { address: string; diff --git a/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts b/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts index ea685b7778..32916efde6 100644 --- a/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts +++ b/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts @@ -18,12 +18,21 @@ const { loadFixture } = networkHelpers; /** Must match `BfvDecryptionVerifier.MESSAGE_COEFFS_COUNT` / circuit `MAX_MSG_NON_ZERO_COEFFS`. */ const MESSAGE_COEFFS_COUNT = 100; +const EXPECTED_C6_FOLD_KEY_HASH = ethers.id("c6_fold"); +const EXPECTED_C7_KEY_HASH = ethers.id("c7"); + function buildPublicInputsWithMessage( messageCoeffs: bigint[], totalInputs = 402, + subCircuitHashes: [string, string] = [ + EXPECTED_C6_FOLD_KEY_HASH, + EXPECTED_C7_KEY_HASH, + ], ): string[] { const arr: string[] = new Array(totalInputs); - for (let i = 0; i < totalInputs; i++) { + arr[0] = subCircuitHashes[0]; + arr[1] = subCircuitHashes[1]; + for (let i = 2; i < totalInputs; i++) { arr[i] = "0x" + "00".repeat(32); } const offset = totalInputs - MESSAGE_COEFFS_COUNT; @@ -68,7 +77,7 @@ describe("BfvDecryptionVerifier", function () { const bfvDecryptionVerifier = await ( await ethers.getContractFactory("BfvDecryptionVerifier") - ).deploy(mockAddr); + ).deploy(mockAddr, EXPECTED_C6_FOLD_KEY_HASH, EXPECTED_C7_KEY_HASH); await bfvDecryptionVerifier.waitForDeployment(); const dv = BfvDecryptionVerifierFactory.connect( @@ -113,6 +122,66 @@ describe("BfvDecryptionVerifier", function () { expect(result).to.equal(false); }); + it("returns false when c6_fold key hash does not match", async function () { + const revertingVerifier = await ( + await ethers.getContractFactory("RevertOnVerifyCircuitVerifier") + ).deploy(); + await revertingVerifier.waitForDeployment(); + + const bfvDecryptionVerifier = await ( + await ethers.getContractFactory("BfvDecryptionVerifier") + ).deploy( + await revertingVerifier.getAddress(), + EXPECTED_C6_FOLD_KEY_HASH, + EXPECTED_C7_KEY_HASH, + ); + await bfvDecryptionVerifier.waitForDeployment(); + + const messageCoeffs = [1n, 2n, 3n]; + const publicInputs = buildPublicInputsWithMessage(messageCoeffs, 402, [ + ethers.id("wrong-c6"), + EXPECTED_C7_KEY_HASH, + ]); + const plaintextHash = plaintextToHash(messageCoeffs); + const proof = encodeProof("0x01", publicInputs); + + const result = await bfvDecryptionVerifier.verify.staticCall( + plaintextHash, + proof, + ); + expect(result).to.equal(false); + }); + + it("returns false when c7 key hash does not match", async function () { + const revertingVerifier = await ( + await ethers.getContractFactory("RevertOnVerifyCircuitVerifier") + ).deploy(); + await revertingVerifier.waitForDeployment(); + + const bfvDecryptionVerifier = await ( + await ethers.getContractFactory("BfvDecryptionVerifier") + ).deploy( + await revertingVerifier.getAddress(), + EXPECTED_C6_FOLD_KEY_HASH, + EXPECTED_C7_KEY_HASH, + ); + await bfvDecryptionVerifier.waitForDeployment(); + + const messageCoeffs = [1n, 2n, 3n]; + const publicInputs = buildPublicInputsWithMessage(messageCoeffs, 402, [ + EXPECTED_C6_FOLD_KEY_HASH, + ethers.id("wrong-c7"), + ]); + const plaintextHash = plaintextToHash(messageCoeffs); + const proof = encodeProof("0x01", publicInputs); + + const result = await bfvDecryptionVerifier.verify.staticCall( + plaintextHash, + proof, + ); + expect(result).to.equal(false); + }); + it("returns false when plaintext hash mismatch", async function () { const { bfvDecryptionVerifier, mockCircuit } = await loadFixture( deployWithMockCircuit, @@ -148,6 +217,28 @@ describe("BfvDecryptionVerifier", function () { ); expect(result).to.equal(false); }); + + it("returns false when constructor expected hashes do not match proof", async function () { + const { mockCircuit } = await loadFixture(deployWithMockCircuit); + await mockCircuit.setReturnValue(true); + const mockAddr = await mockCircuit.getAddress(); + + const bfvDecryptionVerifier = await ( + await ethers.getContractFactory("BfvDecryptionVerifier") + ).deploy(mockAddr, ethers.id("wrong-c6"), ethers.id("wrong-c7")); + await bfvDecryptionVerifier.waitForDeployment(); + + const messageCoeffs = [1n, 2n, 3n]; + const publicInputs = buildPublicInputsWithMessage(messageCoeffs); + const plaintextHash = plaintextToHash(messageCoeffs); + const proof = encodeProof("0x0102", publicInputs); + + const result = await bfvDecryptionVerifier.verify.staticCall( + plaintextHash, + proof, + ); + expect(result).to.equal(false); + }); }); describe("success", function () { @@ -169,7 +260,7 @@ describe("BfvDecryptionVerifier", function () { expect(result).to.equal(true); }); - it("returns true with minimal public inputs (message-only vector)", async function () { + it("returns true with minimal public inputs (vk hashes + message tail)", async function () { const { bfvDecryptionVerifier, mockCircuit } = await loadFixture( deployWithMockCircuit, ); @@ -178,7 +269,7 @@ describe("BfvDecryptionVerifier", function () { const messageCoeffs = [1n, 2n, 3n]; const publicInputs = buildPublicInputsWithMessage( messageCoeffs, - MESSAGE_COEFFS_COUNT, + MESSAGE_COEFFS_COUNT + 2, ); const plaintextHash = plaintextToHash(messageCoeffs); const proof = encodeProof("0x01", publicInputs); diff --git a/packages/enclave-contracts/test/BfvPkVerifier.spec.ts b/packages/enclave-contracts/test/BfvPkVerifier.spec.ts index 7d72c98028..5caf352950 100644 --- a/packages/enclave-contracts/test/BfvPkVerifier.spec.ts +++ b/packages/enclave-contracts/test/BfvPkVerifier.spec.ts @@ -15,6 +15,9 @@ import { const { ethers, ignition, networkHelpers } = await network.connect(); const { loadFixture } = networkHelpers; +const EXPECTED_NODES_FOLD_KEY_HASH = ethers.id("nodes_fold"); +const EXPECTED_C5_KEY_HASH = ethers.id("c5"); + function encodeProof(rawProof: string, publicInputs: string[]): string { const abiCoder = ethers.AbiCoder.defaultAbiCoder(); return abiCoder.encode(["bytes", "bytes32[]"], [rawProof, publicInputs]); @@ -30,7 +33,7 @@ describe("BfvPkVerifier", function () { const bfvPkVerifier = await ( await ethers.getContractFactory("BfvPkVerifier") - ).deploy(mockAddr); + ).deploy(mockAddr, EXPECTED_NODES_FOLD_KEY_HASH, EXPECTED_C5_KEY_HASH); await bfvPkVerifier.waitForDeployment(); const pk = BfvPkVerifierFactory.connect( @@ -61,6 +64,67 @@ describe("BfvPkVerifier", function () { expect(result).to.equal(false); }); + it("returns false when publicInputs has only one entry", async function () { + const { bfvPkVerifier } = await loadFixture(deployWithMockCircuit); + const pkCommitment = ethers.keccak256("0xabcd"); + const proof = encodeProof("0x01", [pkCommitment]); + + const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); + expect(result).to.equal(false); + }); + + it("returns false when nodes_fold key hash does not match", async function () { + const revertingVerifier = await ( + await ethers.getContractFactory("RevertOnVerifyCircuitVerifier") + ).deploy(); + await revertingVerifier.waitForDeployment(); + + const bfvPkVerifier = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy( + await revertingVerifier.getAddress(), + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + ); + await bfvPkVerifier.waitForDeployment(); + + const pkCommitment = ethers.keccak256("0xabcd"); + const proof = encodeProof("0x01", [ + ethers.id("wrong-nodes-fold"), + EXPECTED_C5_KEY_HASH, + pkCommitment, + ]); + + const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); + expect(result).to.equal(false); + }); + + it("returns false when c5 key hash does not match", async function () { + const revertingVerifier = await ( + await ethers.getContractFactory("RevertOnVerifyCircuitVerifier") + ).deploy(); + await revertingVerifier.waitForDeployment(); + + const bfvPkVerifier = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy( + await revertingVerifier.getAddress(), + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + ); + await bfvPkVerifier.waitForDeployment(); + + const pkCommitment = ethers.keccak256("0xabcd"); + const proof = encodeProof("0x01", [ + EXPECTED_NODES_FOLD_KEY_HASH, + ethers.id("wrong-c5"), + pkCommitment, + ]); + + const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); + expect(result).to.equal(false); + }); + it("returns false when pkCommitment does not match last public input", async function () { const { bfvPkVerifier, mockCircuit } = await loadFixture( deployWithMockCircuit, @@ -69,7 +133,11 @@ describe("BfvPkVerifier", function () { const pkCommitment = ethers.keccak256("0xabcd"); const wrong = ethers.keccak256("0x1234"); - const proof = encodeProof("0x01", [wrong]); + const proof = encodeProof("0x01", [ + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + wrong, + ]); const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); expect(result).to.equal(false); @@ -82,39 +150,52 @@ describe("BfvPkVerifier", function () { await mockCircuit.setReturnValue(false); const pkCommitment = ethers.keccak256("0xabcd"); - const proof = encodeProof("0x01", [pkCommitment]); + const proof = encodeProof("0x01", [ + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + pkCommitment, + ]); const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); expect(result).to.equal(false); }); - }); - describe("success", function () { - it("returns true when commitment matches and circuit verifier passes", async function () { - const { bfvPkVerifier, mockCircuit } = await loadFixture( - deployWithMockCircuit, - ); + it("returns false when constructor expected hashes do not match proof", async function () { + const { mockCircuit } = await loadFixture(deployWithMockCircuit); await mockCircuit.setReturnValue(true); + const mockAddr = await mockCircuit.getAddress(); + + const bfvPkVerifier = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy(mockAddr, ethers.id("wrong-nodes-fold"), ethers.id("wrong-c5")); + await bfvPkVerifier.waitForDeployment(); const pkCommitment = ethers.keccak256("0xabcd"); const proof = encodeProof("0x0102", [ - "0x" + "00".repeat(32), - "0x" + "00".repeat(32), + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, pkCommitment, ]); const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); - expect(result).to.equal(true); + expect(result).to.equal(false); }); + }); - it("returns true with single matching public input", async function () { + describe("success", function () { + it("returns true when commitment matches and circuit verifier passes", async function () { const { bfvPkVerifier, mockCircuit } = await loadFixture( deployWithMockCircuit, ); await mockCircuit.setReturnValue(true); - const pkCommitment = ethers.id("committee-pk"); - const proof = encodeProof("0x", [pkCommitment]); + const pkCommitment = ethers.keccak256("0xabcd"); + const proof = encodeProof("0x0102", [ + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + "0x" + "00".repeat(32), + pkCommitment, + ]); const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); expect(result).to.equal(true); From a8379b4a72cc6b8fa4929723b9cbfcfa8dfc9e1c Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 18 May 2026 15:45:21 +0200 Subject: [PATCH 2/5] update benchmarks for insecure and gas utils plus more testing --- agent/flow-trace/04_DKG_AND_COMPUTATION.md | 19 +- .../results_insecure/crisp_verify_gas.json | 58 +--- .../results_insecure/integration_summary.json | 102 +++--- .../benchmarks/results_insecure/report.md | 92 +++--- .../scripts/benchmarkGasFromRaw.ts | 53 ++- .../deployAndSave/bfvDecryptionVerifier.ts | 5 + .../scripts/deployAndSave/bfvPkVerifier.ts | 5 + packages/enclave-contracts/scripts/utils.ts | 71 ++++ .../test/BfvVkBindingIntegration.spec.ts | 306 ++++++++++++++++++ 9 files changed, 556 insertions(+), 155 deletions(-) create mode 100644 packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts diff --git a/agent/flow-trace/04_DKG_AND_COMPUTATION.md b/agent/flow-trace/04_DKG_AND_COMPUTATION.md index 98eb079eb1..939b05d02b 100644 --- a/agent/flow-trace/04_DKG_AND_COMPUTATION.md +++ b/agent/flow-trace/04_DKG_AND_COMPUTATION.md @@ -601,8 +601,15 @@ ThresholdKeyshare receives AllThresholdSharesCollected │ │ 2. require(publicKeyHashes[e3Id] == 0) │ │ │ → Can only publish once │ │ │ 3. require(nodes.length == committee.length) │ - │ │ 4. publicKeyHashes[e3Id] = pkHash │ - │ │ 5. enclave.onCommitteePublished(e3Id, pkHash) │ + │ │ 4. When proofAggregationEnabled: │ + │ │ e3.pkVerifier.verify(pkCommitment, proof) │ + │ │ → BFV: `BfvPkVerifier` (DkgAggregator Honk) │ + │ │ • pins `publicInputs[0]` = nodes_fold VK hash │ + │ │ • pins `publicInputs[1]` = C5 VK hash │ + │ │ • checks last PI = pkCommitment │ + │ │ Redeploy verifier when sub-circuit VKs change. │ + │ │ 5. publicKeyHashes[e3Id] = pkHash │ + │ │ 6. enclave.onCommitteePublished(e3Id, pkHash) │ │ │ │ │ │ │ │ ┌─ Enclave.sol ────────────────────────┐ │ │ │ │ │ onCommitteePublished(e3Id, pkHash) {│ │ @@ -613,7 +620,7 @@ ThresholdKeyshare receives AllThresholdSharesCollected │ │ │ │ Emit E3StageChanged(KeyPublished) │ │ │ │ │ │ } │ │ │ │ │ └──────────────────────────────────────┘ │ - │ │ 6. Emit CommitteePublished(e3Id, nodes, pk, C5 proof) │ + │ │ 7. Emit CommitteePublished(e3Id, nodes, pk, C5 proof) │ │ │ → Note: emits full pk bytes, NOT just pkHash │ │ │ } │ │ └─────────────────────────────────────────────────────┘ @@ -830,7 +837,11 @@ EnclaveSolReader decodes CiphertextOutputPublished event │ │ 4. decryptionVerifier.verify( │ │ │ e3Id, keccak256(output), proof │ │ │ ) │ - │ │ → Verifies decryption was done correctly │ + │ │ → BFV: `BfvDecryptionVerifier` │ + │ │ • pins `publicInputs[0]` = c6_fold VK hash │ + │ │ • pins `publicInputs[1]` = C7 VK hash │ + │ │ • checks trailing 100 coeffs vs output hash │ + │ │ Redeploy verifier when sub-circuit VKs change. │ │ │ 5. stage = Complete │ │ │ 6. _distributeRewards(e3Id) │ │ │ │ │ diff --git a/circuits/benchmarks/results_insecure/crisp_verify_gas.json b/circuits/benchmarks/results_insecure/crisp_verify_gas.json index d22685ed95..42985be404 100644 --- a/circuits/benchmarks/results_insecure/crisp_verify_gas.json +++ b/circuits/benchmarks/results_insecure/crisp_verify_gas.json @@ -1,8 +1,8 @@ { "verify_gas": { - "dkg": 3037922, - "user": 2973073, - "dec": 3549077 + "dkg": 3037910, + "user": 2972965, + "dec": 3549222 }, "source": "folded_proof_export_plus_crisp_verify_test", "artifact_sizes_bytes": { @@ -17,9 +17,9 @@ }, "calldata_gas": { "dkg": { - "proof": 170112, + "proof": 169920, "public_inputs": 5504, - "total": 175616 + "total": 175424 }, "dec": { "proof": 170100, @@ -27,53 +27,7 @@ "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" - } - } - }, + "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.115728250,"runs":3,"total_seconds":0.347184751},{"name":"CalculateDecryptionShare","avg_seconds":0.608609847,"runs":3,"total_seconds":1.825829541},{"name":"CalculateThresholdDecryption","avg_seconds":0.578625417,"runs":1,"total_seconds":0.578625417},{"name":"GenEsiSss","avg_seconds":0.124242194,"runs":3,"total_seconds":0.372726584},{"name":"GenPkShareAndSkSss","avg_seconds":0.223503888,"runs":3,"total_seconds":0.670511665},{"name":"ZkDecryptedSharesAggregation","avg_seconds":8.568398333,"runs":1,"total_seconds":8.568398333},{"name":"ZkDecryptionAggregation","avg_seconds":49.047040500,"runs":1,"total_seconds":49.047040500},{"name":"ZkDkgAggregation","avg_seconds":20.151443750,"runs":1,"total_seconds":20.151443750},{"name":"ZkDkgShareDecryption","avg_seconds":1.504357312,"runs":6,"total_seconds":9.026143874},{"name":"ZkNodeDkgFold","avg_seconds":62.889247500,"runs":3,"total_seconds":188.667742500},{"name":"ZkPkAggregation","avg_seconds":2.156797250,"runs":1,"total_seconds":2.156797250},{"name":"ZkPkBfv","avg_seconds":0.328596097,"runs":3,"total_seconds":0.985788291},{"name":"ZkPkGeneration","avg_seconds":1.329930791,"runs":3,"total_seconds":3.989792375},{"name":"ZkShareComputation","avg_seconds":2.693458527,"runs":6,"total_seconds":16.160751167},{"name":"ZkShareEncryption","avg_seconds":2.489975329,"runs":24,"total_seconds":59.759407916},{"name":"ZkThresholdShareDecryption","avg_seconds":6.047533777,"runs":3,"total_seconds":18.142601333},{"name":"ZkVerifyShareDecryptionProofs","avg_seconds":0.097465083,"runs":3,"total_seconds":0.292395251},{"name":"ZkVerifyShareProofs","avg_seconds":0.226985783,"runs":5,"total_seconds":1.134928918}],"operation_timings_total_seconds":381.878109416,"timings_seconds":[{"label":"Starting trbfv actor test","seconds":0E-9},{"label":"Setup completed","seconds":3.041689125},{"label":"Committee Setup Completed","seconds":20.243337708},{"label":"Committee Finalization Complete","seconds":0.007484375},{"label":"ThresholdShares -> PublicKeyAggregated","seconds":304.504600792},{"label":"E3Request -> PublicKeyAggregated","seconds":307.024598667},{"label":"Application CT Gen","seconds":0.318660917},{"label":"Running FHE Application","seconds":0.003694084},{"label":"Ciphertext published -> PlaintextAggregated","seconds":79.271051417},{"label":"Entire Test","seconds":409.917920083}],"folded_artifacts":{"dkg_aggregator":{"proof_hex":"0x00000000000000000000000000000000000000000000000469753df342aec0e0000000000000000000000000000000000000000000000006e4d829d66aff749d000000000000000000000000000000000000000000000005f6499be2b18300b20000000000000000000000000000000000000000000000000002be6db4c5558c00000000000000000000000000000000000000000000000eedb4b6056c881e3400000000000000000000000000000000000000000000000867b55169f2600f58000000000000000000000000000000000000000000000001bc9f519f74446bfa0000000000000000000000000000000000000000000000000002b6d6df53885c000000000000000000000000000000000000000000000007269f9ee62308a02500000000000000000000000000000000000000000000000fc8ef0ceed9608e82000000000000000000000000000000000000000000000002d32a3b72f08734b600000000000000000000000000000000000000000000000000018a5af26897d800000000000000000000000000000000000000000000000665ee11e35db35bab00000000000000000000000000000000000000000000000c29f716629ef9a6b300000000000000000000000000000000000000000000000ef868c0047d6dd22700000000000000000000000000000000000000000000000000026ab8350fbcd619e3c65ffa1c0d29b2cd62700cf8d71ebcb032227e21f28af6c3d9993353159827a80a592b60afb7bd0a5547279d7b7b6d745bd21e61cb30dd2fe6fa64ed7ee81bddec82e6608821134bc64e48afc548d54643761d84f4518e91e1bb576a9b3a1efdee0270f6a11edde9c2fd71e9de5a134a7ffcfa996506f17b7ded320b946905e9267cb38c0568773f0534e90cb7b63d7211d220cf75c33fef50d1b5a5100e055a47bec0d9798656da3a784b526caa90e53303c14eb63b919c2949535645bf0d9547c8dce32e13dd504bc6be4948f9635a4189cac34427ead69640255ad33c0d14a348d9edcbdb6ef4d4b0a379e7fdeb9801b76a0da963bdb56d89ba8f3a0210b7c42426c99152b8bbcdf2b36f1c1855f0ceb7482c347de29259ad7e05498a03d6dc7925daaca12e8661b8410ba878a1497660cac39150a0d2d1ca7b556cd5217867ffbd422a5ec0f3eda032d0da1dae248fdb76aa76f2aef8583db964d1491f5aff0a8af8585259f308839565b5bfa984c574d4cf02f2552749a67f4ee7f91fd21add31916d3b40f4006b7a83ebf00c14999182cacfc3b853fa33eb52c4bc0d7a9f47486d5c9f5dc5f1fba6a4c5edebfa27f2b9d47ef6a7de0f966356dfac080b3dab741554edf23aad2a27840334a132e4ccc09bc438f503346aad442b0214216a2005c8c7a405b68cdc0032c8a6f8ff1c663bfcfd165d7de791193c31c30dd9f2f2f2a0431be2e4e4f1fe5b4be54f4df8b761ca81b8634e42a243789b7219142015b3808efb3a739c019f139df3488006f7e463f6d19fcf228bce9fa6d613cc0c01c36911240ee0501a0cc007655ea1fd15b8a1ad2f8d1ddf49931bc0bf177827b2cceb2956abbee92ecef40924cb1e618efef90f0194b8d8df4745ac94211fbc877e3f1c1843dd9c04c81659fd1071b38a33797f6a6c395143aec09c8901b9d02917af3362e348cfb2e9aabd53ebbe6b3565508163ea1901f214764dda2cc1ea3a3e121b0655786495091b1b6eb05be9d77b5149795f94e4bec6e2b183149dc7fb2a6c49197a09199db3d00a13ed9d3fe11a18f5fac973b7349533df4922301951689c04b3f866c7f8425c047237cf8d409e8ba27c49e924268817c9e9055066deefa06a0b869217f5fed30835f92bd9662aca74e8b06d29e525ade59a1fb24ae716ec7d331fe77e298f28024bb1fdcc10c4390920b5592dc36749909d0c0f625429773d2393a4f713600cabfca65ec0617333ae5764f69790a9f97bab2f003fff339c5965274e74d713ade8d48df30bf48503c109d9e6c124b70b6277299d62ad7b2b7138796b217dbcc3c4acf6017e1bd6fdbc366957610a0f79eb4f17ed4c180fa64e56f7ce6c9c3aab320f1552db2274fcd7a4576de6cfb0d3db3c1ea4b1ce1f3afd3ab96c2e78be599e3d94f43d7f89851fc6ed825d6658f005e815a7cd1bd26641e038a56293b8095be2f287d24612af3ed6ba44a1f3f3a911e3302a5476eff60236e0580cf8b25f9efc8244b30ed8786f66e39dd4456aa4f024029eba613ba4fb9a7994e9ce5afb6923109490c62e0c988df549f2e9dcc3a56829bb3f7054a4b8cab4aa1769fa658620e87d592cbc03f9a71bca647f275288ab02dab6867241f0d9d7a67a4b33933a1709d75274bf5bbdca414d3ec79ed120fb064ea0f18c25252dd3a82b941e656196dae6336b385dbc60cb74e8cd668c6f631fa549c5ccb417790c6e015e9adb9d640012eb6c177e18eb7a319e4fd7a266671c31bccb4604b5acb7226d74e075d4276b4e9410a595e91dc5f864d35c6e95b72d4308c3be58dc29da40e25d1f63a36940f572b901c39f31e355b075dfc95a2d2092ece23729f1bf832fac0ec1ccd994f016562ca1efebf54428b688f1603df1076714c5d7d7ccd14a87225c15c5178ecb331bf323ab74f8240715fd0166c33605affcaa1b4b75d30f034659860df6af13b6ee9e6e5c1cbc5e131c2709ea226c11cf137940d661f8f254ebfe274cbd889768cc23d728cd2c5082012f427228cd21cf49509a55121e5756aa33e207a548d5a8f15e9f4869564fb2fcef1c4577e81f237f271365e73cbe12dfdee90ca49799cfef0cc0af26d57ac820007cf3cfc9073dcb3915ed77c7e50f58441879c2c5bb450ada48fb95182dd02943e980031a257c5bb6c116e0e17a1efd1877dcc3a988d9b5680f05f5dd7927bbd0336c143c0aa03fbd503e48787f9296c4cdb00160adecdd0ac45174988fbc535e86d6e4250b3b669d61dbca0afec215f54337b74b36820a3794c4824c9c812aecbdb860be238bcc0ab026c45a1329e6ccbb1f0e6abd83cb9910e5468c9e22ce6c4c3c5d1b2892318212462091cc6f082e3946445e67456576206a0777bdafae6420bc108d0d545b60b47a8647c9acec31abd3eb4a940ce24304658f9ce2ff50a5f5a656f80dcec5d9ed6e857d317c33e96e97e19dea73112a08b301cee1c5a26264b2033918a03534a00b9812d0dd992842efea7d0323402034bef78dbc11232402264318246fac64ff0d90acbd0b1930b4377ba08f35e91ebf526c3802640b74f6b786ec118f486e979a8f8d9bcc19307bee149a5a4d459a145723fa863d8230753eb1dd08f4187ced1f037867e3308affbc4fd535746aa6760d018f75bca7bf3396a59902320058d6cd5935e44ea6943d47fb9d45ccdbf8ef6de9a5231e2e4e2a1558662b10e223298ce2cc72aa45a021f1437be501b2743c08bfbc9708db8b2cd7a9ce17256be9fee29f8d3dbeffea7001aa6648ed7fdd53c0e9117d88379f75466d7c2cac187ce9ea645f137c8531c417fa019100cbdf78be2763d38414b97a6b00871a954bdc2d8e1df7970a636eb0e9d8e5acaaf827e955adfe4a8a2a43598a4cba094833c3e3dbd1f261a5d75b5fd313a5f240ff30d989823dc45a3c3ec90082c626ae27a87be9dadb61eff083583ee3568378e95a1ba75f4bfda023c820466f822adc5410bfa974d63142c051bcafb9f1b00ea44385db8cf1d0c36be3e71899c00cc356ea4a7f52ace0bf72913493c437e3a0cda118619333e1b503b29a7e008a0159746030e90700e49f97c957078dfe35497ae3c4fab77cc9c6f080f84637291d9bd340a31415e39c83c58e3f3b901ccf2e2e2356feb40dc496008982bd189118de77f08ce5a1515447c4a04a8c35e9c89f86d164f10d3df3c3701d8148e5681c027f18f613d5f5d6b22de99a7e7c5d1154db617adb0f4aa4b140a4cc4946ba2c6a68f07b9c6b738d4039291b0e7bce61dd330aed09aadba81f6658e15c46251c44e7e03576d9a2d902f93d2cc226b10a6e44adb7ac928f8275333365101c821d0ce2c8b77aebdb5aabffa4c641b602cfb62c3c98c9f966b2d950a193a4c6e4196464c9eab169d15ac12cf5c4ba880c3bb829afc21ada4364d6a4f81299de8b21679e06e1e557e7c831c03cdb1b8629cb925d4fdc7d44fce7f4ec1517897ec72a2ea327bc07437e1a70ce03392e1d739c2f913698ee590e86c3a7c5e01e70292b73f7dd483bd896583d2bd30e736926227cf981f05cd4d718c6f8025127da4b205d377c16c2d412e76aa1486b04538dee538376fe1522413e41df227cdd52e72c8c867f4a3ea87ee1328f964365e79338fccb36c83a0518445e3c09aa2005ef15405379466c46a41cabae490c736d70476264f3b78287804bca97b68bef27c409883a5ce11bb36fe046d33a2447f7cfc35506203a2e3a01d389c060aa3604cc237fbc043276f8bcbfb7d2d1adadfaba9cbb70a9220efebd6ffc62ed96bd9bf02387189dc44aa75b967986a74ece75106f97c17256baec95737d6de103c6d7a2118ed1f68bbf4fcb6647e625e0a210b31dd9399f49665aa4c27d88a639767a521dafb03ac0ee4f48394d53fe6d209740009a1c11886f6c721cf91e29e268e8cb2a7dba0ab3bcfaf639f230f5cc32a443d1f9afca79a77113657e12b3a4023f130838602c3c9bcda88afbf7ce8fddd16060ec4e0e955bffe48ce7795a750121a7304f58bf35b291bff1e28314c5e1aec8a7301a178b3e2e76b81f27951a2550b817406d894712963faeeed76b7069a0c164e685255aa0ec245c5d223b36b05f760307a8d077c47184df6356e68a3df1b6e645a7a1f68c3a4ec30a79497dbeee8821f4cc5aaee04d9c0c28cbe66e5cbcc48994a4efa36572343f005e385aaa301e157faaaf53694d880169b06e0699f6aa01cd14868786ca9be54a5571ea0791df156e53a49573829a7493415d75ea54104d64b800d4688fe718eb4069b59f93162277d97ac74c5836b5078e713d2181bba46a58bd1be7cfb2d359473be276081f1b6ccb434bbb6f226e9188bc9bcc75826becfb2b589244ff57e97a2994682a3e007aad5202beb5bc1a5ee1fd908cf63b2d36f76e04978c164ce4d36a3646d7581474432c9e22f05b48726087539ee97f746f73cd9d414d242ab5bdfd7609d0b32155a9da08e2067a889517aaf8cb024a8168f94dafce6f93b2f12dfc00641d5218c35fd80cc79d0b4bbb1f766f20ad4ecfc79ca94562895c78057587e9edcf1211fca08a404520fb20794782ed562767d84c1e6bd5d1121a2b58b63d633cb3d528392519b02c9a33d6200c2b94bfeae8eb83460ba6ad4dff419969ce80ad48540cd03c06c82c17abae5a66cd8db314d6cbcfbed1472a446afe81b08ee8e710121bbc002b678d3e50d223f02e4edb538e65fe35f26fa0d21cd77169d208d1cea6188ad9b99abd82c6f89525f6f1034be005f761a9503d049c955ce43bf0997e192ee5118d2c94ab12ba2df5075f42f1572f28660109c53a4051c8aeefb2015915127447e3992602c10f17fa0248d4a63d3fb51d02d7c87575ddd2a228838d54e015405e3aeeb0eda949ed50111d0881e0d2eface34b66941e9ea7246365202f1d207ad9eaf4c7ea11527fa2ceb4c32496270b04edd79eca3542d97606c3ad946601d47aae61d27411aabf3fb0d5c57301ee1ffb7c01ceb4d04ff39180475d097f2b07fc67bf89790286b97b1d814ee45b760d49ddecf8dc3907cfae048afc82550a7f416d7de4c9a6e3a847c5700b4642b637ff9872096679d2d5921eee91c5e11110a2da4abbceb28aa0f9b4bbc132493a2ec0f2712ab0d2cb8d2c589168f9af2f14df7d9de5d4463ff031988639bc2bc42c844a737ca569dc14045284ac011e02992542a5ae3e06562f08bd9eb6d695652b0c0207c3514b292402a5745a60cb22cbfa325db3d30866e1739fe38aca41517e9076700489344ddf68c38c28ae9619b91304c3e55c8f4ffbb089b13b2f04ce5d61caad3d2cb54341b5d1a930d35511de0fd7e69802c35962bd45cd5733a23093208051359e4257f5c9cf68082b362f3744ac22c015a9ac28540106e7d03ddc305882758a50c372a580e5d70c09a720755d74fa777039850e88a289095bc3fda6e3de76a661307c2e77237916761e1dc2e2fb9e5e3e31b522be2e0d8f2e3e7e9cc1dfecb73a1a79a0e26c7c9083080a1e1842116ee304103ebdccf52062bf9578e864afe05f3983c17b84f7bf4d1209460b438ba34839d978ec1c5bf6aab43d09bcada67751ba23a5d39910102bec0c09b6ed88010416941c845ff0402963a715b14ae1a371e9f1913698b402ca86250046ab1d84ba0a6bb12686cac9ba831fa28fa3d0ba72589da190425b42548e220351f64ece113e51fdad160958af52e544b5d08fde40fe37bb84cb659bf593033e291841fa82a53a8f2c141b596c4ed461f562e632b2ca893c12a53bf0de5d2f084d18fd57562a366766d549e205cb36846670c81b92ceed909400a673e53223e9c3b1001c31f367bc9125089c292d5c65dbe914f59cfb0c1b702c7847f2151732806c02b5aa5e97871f60839b79d3e6feef3a3f696115c06e05b0429e1d5321042be272a689d6010378e100c44a1ea4c1841d88a61ded92b9c04347056b3e098fb4e93729884cf98a415354961cb468d38c8c5dab2466952e1863952de5d22bce831cc9e2f11fc39a4e1911e4e391aef8fd7e2f2868e7e8593519a4dbbafd163660310bbb68814e644e234d2a6214d3c2d84d5e78091ce6a3167f992d6c411b70840ca25c4251db8cb551e4a37170bcc4e0aad6a73ca6eae85ae85437a8c12fdf8773e4d6896da6b5510c65e8e5ebe2214ce0aeee893aac3b5169ace00fd20cd9084610949486651f579981d04ce71f246593a621b94b11bf2d4a53a9b7272a75ec707e5d6e9b94cba7277335b4dbe3a721bcc5d8d33f2d6521047d8b2e33035d2aa05920b16961a8e9f5091d1e8dcb0ef43ed663dd29d95e24307a3cbb14248a1fde5949b811c8cb64d561a5814c4e42db4c2a82ed3f85428951892885a92727050ec02883b4fae76a8ff11f88b279cafc825d492c8d88e6a21b8069bdbe3020b22284e21dbc649e9fea5576619b0d5a6c20662adc00a8cae9dc666fe84d2a33893fe7fd23a4b3602b1872968e09b248a1e5f009b8221019113733a639e314bce17972dd81107ac90a257fb403b80809e8a41f298cfeb0be9d87341e9e8026b58446c8f6efe18ba6b664917d764b67f883a1573207364f3a05ea5ac4124a247da1fbf361caf35db0991d02d7cbeec4e6867b454e1c728cd64859a18ff1d72ade435bb8dbed3cf274c0830a6adc7e9aa296f01e451882b007fd972875c54a2a76150e904347222648306798c03ad2eabf742dee661f1ff2ee8b7aad5061f408e8c42347c0400fa8fd99c1e5d560ffd9c45e274bba4f8e3de5f6899a9eafbc05c680f29f0e759926432803bd257f347279ad57e0cfae3ac1820766f2bfa89a2a054c1318608489a6149c8ce98f751f4f90897fa87921b04885242913fd053c29d2250a857eadfa84a16b5b4ded1c2f89d817a2e005da0b94a425b9890920c829d60b0fc66656f0a79faa3e5496317705e56c49f69b3732213b652469ede8b62007b1e8209e5e0eb0842a86321e49413e7d1c48539b8c8689d932b368452d8f00a415eadc12aeec854463da5ec3e848343d7e035b69fc369e03b45d426c80cc21af387870e76a693d616c271e15dbaf75d32b19d1e6ccbc63ac71e155d002ad2992a221a39a21245e9ce4d06a5d450398bf7fdad0fcfc4edc1f12c3a109d98d1b24c341201ab7ad61528931ed868d4ae748b0935ab27304779ac23257a0b4e40fcd390fe49200b9b9a086a7756db0a14b232ad01be5356c40d31c1aea918a7206b55b1f8d4af81e1cedb29c4368641a2a5d2440c70d6908fde350ac8a26c7f22d3b2f21b2c3632af0f2e9f3c9e52e99d9afb03fddd83f09cb28d206f67086000dad45940c134287e81c13e4bb5bc22ef82e4c5e061e69084a781a21997c063010b394acfd38162430147456b9de74aad70a060df546ca38407bdcbe464b01aa140d5bfd0a61d5158d157b2f9eb42ee971192939f25f02448cb5782b36d5ba5413dde40e8944b03e710c31402a37c420dacb73603c0e62af12c136f833aa3437064f488a6685c8f0b0c291eb33aa33b81a9e4c513e6ac55c7175c3073335d9740cfe4ba38839d89625ce94c63e04178c0c76553844241b8ffbf82c53237a02390282e7cff22065a0568345157ed5e428b107946d5003cc6ac9718b020a21e589158a93d1249c81b6f5edc19b1a461d4886f40991c89be5c89ac77ec5486d77b12852972575eea908a0d0ad066ab7ff71ff02720e41b559dfaf5cc99992a1e82b267146784c9faf18f0a30b1d2c8926de25b4a2b5d4efcf00aee059031129823405e5c2b04465b50e6a6300c519152d3b175595d3ee4a7c103c90a46683bf33900973a27e9d6caefb89a1d148934865286ceceb2eb2a6dcffbf93f40d6b8141f32df15c9b7528bf722ac0cfcd16b5d3b5992965d3f49c62a5516dcafc36be9bd117d498ae3e827c74807a0f6120713c018891bc502fcb2f3a3ef5df92fd36e09123278dd884d45abba015519edebefbbe07b19dfb6eee736e611a001af8182f7d28d2df78f84999ed714f241de56318517b31798f9bedfae1771e43d28c74ec01236fa605728da81f251b890f3ae9375925ce406c5808328b62d0c1f61d507fee0d603e2271f6256b38c56b4d51698152dd71d572f18aef64bb8956cfdbbac8291420757829b48a402faa763299af4f927add42dfe05421d6f381015fd09950cb1d49db81efd5ff650a753c43ef4d6c56742c82663cd9ccde44c04a9d16efb3f226f10221eb3fb7fb9cd29e0ca0a9bef0f9b7ce84f43ea5bf4c7497642e2ee7ea1cfe335df4a4cac533cacec297ac86541cfdbb6baa5d5ac993ea49936cd81b391fd9942ed996e79fa851a07adcefd1c2a8b8f57810e54d04a23aacb01abdaf8d2e2bb8819d1ac0ecd13c2e7af62f8407d63039b06b61192c4d7a82f65bcab66e05e769b154a29cc138b5119a732f22dc15ccdd3beed12318162f437d9da4532508b3af66a3e7a10172a476ec9de4a05d3cef956d6ad5bfbb0ec8923723117f5a046ef296f2b5d88055a90b443c25e5b0b877e3474f28f2cdc79f49c618f44aaa02d3d1638363ea5018f4710ed06eeba5776f89dc9dc4afc3fe942f92f90326771de423f8057cd1463a148594606857c7410f3de1767f89e692f64aeb9c80dbd6063943261cef4c11bf08aa50589f51ac7125d9fd81d005b2ddf1d8b1c5e7f97512b4bc9df1655304994d4c05d0881eab395a5925b935d565194e3db86ea73f9e0cb618907cb0aa0d73720855ad56a543d380344559d846d0c87d2f66c010826d2f0a5280fafcc55461e94a95c98123087fe7c5afd72020c01b5bb159507bac36081c5efff00bc7e17f6289e9d2c2c5e9beb2bf4dc4465c3e954f2393e70ceac216ae4898e4821f8dee3c88d8c1085a01d6abd2a23f0ff1f6b92df037992c73a602cdad1370bd59f65f93ed6344a19ffcfae76acee1f8e2444d8fa27b346719541a4dd20cb3c9f3dc615bac655270d1362c9edad97c23f13b6897d65ef2e3d67b2e948af7af733a7252895958bf669fb507eae810fcadebad364fbb3b5d1a68a1146f82fe31c5e8c26c46d4fd4d134123c591bb36cfce94158faadd437ae2ef3920ee3821c8ef268c38cdcdbb380ec23ad56abf2c5cbc9fcdc291c02269af47df0e6fbd50a5e974c1e50024975c390f43b6da32df921c90f11d18d6577fdc99c120126a58a070d74d076cd1b872e0cbba7354f30dd38057fae7023c6dcd63527a1c00ad87e6e3ba05bda510ec142acd5a3c662373ac3f7a7cc8a10ed678466446176938d996ea81ab6002cc8f4c41e5269d007637a81878e6bf0bd562e0d1b60e10da7445419432b35618cd61bf90079a08b5a0fdab94cf8f36d066351118484606ed4fbf014e02b795dfd62b14b16ba950be77d5c317dd70fb058c0d896e18a1073024ed35b213beac45d0eed9cdc684c954bdf3c18f365dc541b68618b8c06e1d8a83550339c96e752a82d077cfb8ce0211447e4bbdbc3b127712004fb7caea05d2641dd30ce23b7d8b9c5530671324cc9aa1bd271ac6c9be835fec30741fa103c877e6c320cd6c0bab7d62d3bcb698b6605be618784663158b717f37ab03000f60911e4d3e33184fd26170e83152da85d24a8f095334e59b7b62cf4c2ed8400688807ae631070c134aadb8290c356a9521af9333a69da38904671ef89c4d97004d118138a5d8f7d945a78c0abc64881ac3ab0c86060db570be08d3dc2445032afc433cd6ea04a649a3b523471a5d2ad1431f3584f5142b2b5046b5f39bc69d16565ecc4219043483b3906d8e2623ca40a26cbf9f18f51ac5259545a592d5f827e0ffe8b7ff77b8f63b0ef131ffa4c5667134828fe82cdc754d15c7cd33cb6c0077f04d332e7ddf9956d603ec3c9c0a55e1db71f19642c7f876452248a70f3b1cdfb9da087a8ca3055014df3aac51deddcbc64dd8d5a8a221d8e91e749b308113fbabb99460f5785f829d0b922389a673cb6dd7cff8c3d288a77f07823028da1292b1f04a858b4630c8306b8fc5226f918328babcef14b9dc10c1880582877e1d450f991999bb052fa475bef0846a915a9d643aff92ed06420fcba96e673339288c3fc6586c13eb5f581e6e7200163a5e011881ebecf259bf2b84139ede52f60e389ecb2a3b2d75a3cc041b4fca6ef2cb232527ef829a8476563013a4d336e204e8ec63f06e0917808f60401e320069d022f661d3ba23965bc66155ac3623f30b29bfc132f9b01495f4c869c57e8cc42cd2242e72fdca3ae4727c02d9ac881c0a145fa3f17edb13347bbd19819e570e3b016cb952295952683f30761f4f03cc105cb9a489ad41d21c68151afe3def6129200c5de1b932ab352119aeae31df5121e519547cd28f05371a2c65f716c239ab69d20fce2af689bc05f99ce4247cfa29cc49b35b4358a3b42ae5c91d95fb99655002e2b0d6d535f21a6c58b9f82a2119649e434ee728c3248ed73b956bb9667ca6b77443651eb331f0b6520d62c5852e3370acf4ada80391db77ba155e3aba9e8d821c2ce1d31ec09f9898ac21b1112dddc3ef15cb12590a98531763b8d043596632648e08f8b80de1767e74855ad7259558e9228544d393351f17db1a37f55314b6d2a39ff65ff22247ce74073deb24cc708bd37b6ff151588a7c0d107521ae217f13afecd55265888f3263cb2bc924a1faf27e8345e2cab32ebc6aae03b62d115631527b68761882befcaea90c0102a7abe55e1764b18199cefbe32acd68f76650b5a83204dd677195396700b93e268fd11b30f6aeae2288c6b31926a50007a0e85eaaf2f7a6c3c040369df5111e1f8e3e91e40e7095ea9820a37d8ed5408382dea8fa3be255dcd2432ac79c3b2a1072aee7d8c69cfea210a58c99dd9c158744bc20b17e8dba95c49091b70ba4f4038acdad5293ad3f47569799a1203e607107575ad494b4857aa06a2be9d0d4ce2aa07260c845899f56d89fbfb7e18c24130097b1e41bc0ec6d7243558f2191bc1ee0b5ece2d0d55c02d3abb80cfd8d10d6bbf360068dcf6cc17debe3a4e8ffa3287fbddc25ef9071872116ea57fb9055a978d85768f3dc162876957749af16512290c1d094e99bde4c38c864d31bbbf85ce2ee488f943be32e2727633089385f2b461d8ca9e0855827cda5fb219fb1717ff0a838ed1b27d82947288e5e8c14590e039cc9b1ab4a33501362144ea57353d0ce3ae7f845bdaecd9e1304b5472ff61d5f0fe5673507d3b79974ae6d6294e16ef1918a4fa4a8d023e89823124327d21b74fe4ae3c1ad52801ad8210a3cefb6ddc0297038ce08f9e4f49ae8f1f99e5e293e702e81f1c7861c1c445fcb48d92ba77eea9b250ba2967d506925efef7f261ada0b3d9f2742502c26d1ac9f750649cf0155a7e327a3556b2bd9f20e009b9601165f5c53fc4b398b8f3f7413d065aa3fae26a12917fdf716f1360181fd1dc81444a57a6b94fd298742cfadfacd30076bfc6ab47be4f09b66cc76b022a47ca5191e725f35288a70698d51c5cf43b77c2f80b2b3bd4d35c2ea033008cedc2f042eab11def2bcd80ba95c3ee8c4fb917435c62c6aeaf2f4a7131b429b5cb2a4ff23081ade5ac7c55b647aee9aab520bd3869f9c93c36aa7326ca6bff7af3771a201959164e8a0978053f0c13e7a87916c47c7d7ba0d1f1d1c826b8873eb31f7d22a07070f5d5fcad09bc1de1960c10ec0ee3285aa2dc35bc42d8b206ddfe119b621ff709b9861e00dff5f5caf92d33c79082c90e3e9a811cfb225ccf802c6c51e0dd1ffc5d73e22eecdb9be76ac089ac3cbe39613b2e6f4948ae91a42c6ccbe9f278c01e611cb037785788834d4b7306a5f94e0f3bc26e9731c53db35e41fd2b41ea68bb1a63e21995c245b20761bb235c4bdb5248afed40f7531fff2a4e300c80ad0019f2ee27ac9ab8181f077b7a0bebcaf59459cac8ff3758a91b051e89dee24ec65c2bd9503a6ec590079fb13870f775c5a56325c5317a88e5c439303808c0846b44c4526e81fd78c7cc680ed2993cbf600b108e88aeae1e772b0b0f8ae5806f883cebfb726b4263916b6969cac42ca7a9e5910be070fb64d007d0a7315d91daaf0e62bb35b5e24c1e2a5095a294afe753fd690a0f4bf298d5f1d0e3fb5311399d876cf50e48fb817b3e8c7146c1d061f07f7d0710e182991462d793227590788cd56236e23963e9a41d9b6fee0eca464fe0b5ecc58b78151f57622a97ca700863f02eb1bc9d78d1082feb4f383d1e2eb5bdcfb4fd72020922208eb19f7e809e9e7b184a15bfa5a0a43863b5de3e191059cb78bf74c53bff6104e6c5637ad0121186bf2df31b19bf8e87fc74d1c71d8d520f181c275958a409dcb7bac15021cc57260697c1b3bf9c2db1a1e87f6db39677caf5445f6e85853823a0d358472092cd19d6850a62402d1e425a2d7c0fdb61d2e02f86928c3fbc56d2ff048147b07b2e6dd21224c6bfed79c76e49a5d79a1da6722776e2c4cacf6a71f4fdf8c3421001e4747173ea80422461affd27e3af8ce9fe9eafe6bd76e47ca4bfb9f54e01787798b5ebc4cf20038ab846044605785202d2ebedc82441c938599daa982200676dab42c70099280328e8899465ad1cf74bbc27cefdbabdabe85be02dcc6be2780dce9f7f6b97c77bf7284dc71ce4fdf48f13b36553b372bde71f04c1010f719c9e06ad95bf42e16fb4c5e9f5779cecc8a99830b62e6452cd80f8843dae91517bca2479d53cf305a9d43105eef240fcf12a391e92c49596770405de304801d27b4f39ddf78d44201072df5a66c3753d6cc740f42fca640ec8a9c2aa509941c2d8a8d9dda693b87dc33c5b641332770cdeff855b01b7d48304376e48925c963036bce8d831d7efd5f879447cb403c7e4d7b01c62e0ded5dbd39ccdbb545c5f30bdff5b42ced0c62cd22918e3598f7a6cb7c9cbdb7cc8cce49be5fb57fedbf702e06430500eb0bc6b794b6172145c3d7e0b18e36f98f98861f8dcd0511b707b91dd03caac365db1699acc849db995026ffed7dedce3505260acbf7c4b09aca9d0b09ef40ff6a704425e1195ffcccffca50ddb4c9cd440fe5d8f918774b2852b7177d38c0a40a9325dae46f5c11c30c0b4043067451cd714925e0799f22524d0d0c2997d8d76af181579491ae7893f4d087b1daaf0a5e38723690b34d70a1d0d32b0eff8e2c99c5e155e65f42c60d0fbcc7604b757896e0910f97a1f49f6283ee2e09e4434f0300af0e0abf8b98762f5c6295427fe8e0fb6748b7e7aafa26b02b1d819b307c1f70a1a3ab3812f41571c1b85dbe9603288f4afce9591e8449d99a0c07aa3eb97c33a646725cb03d52fc53ba19064ce10ae7544921f23c2eddae110359572c3d7b81433fcb47a8ed65977667fdbe70a029dd1f9ce9dfa4db220f8a2bb209257dd8d49b864ae9621cd32e3772d453207bdc88ea8be26869afcb5a3c114c5ed52c900da7ed5489e6e199c7ff224a18275897d832bfe121afc7d663750613d5ad6f4ca266eaf1f69c6e0f1617c647e6a5830ceeb3f4d5a2e70730fffd259aed34a0a6d955f29fbbbb96a7051a9b8aeb3de2c077dd632f0f91ae4d2fcc13ad02527dcaac974cd68ce11d09ee138b586a61ea77db1f4d8877146da47b710d5e19796318dca7b99638e5450448ed4b0776331585b6846d0b3f504854665421ba13580166db9ba74f35923efc566aca7d76e32ed30283f7c5b96a12a4cba7130476d1a3b19df10ba213cf604761861d3b4264b342a68811bcaf6c26c4ded5189b15e6f0deafa36e7396871fc0054270765d9cd75681bda91ef8f1f156f51528c7e724218c156417cabe8378dc773cd875b748baaa0360dcfec3f8b5fd79fa15758af830260018537aabe640e55fe9e8d3ba07fd4e849035112962edc1ff6d26a4bfa0e267a938b358a6d95d86a3208e3a1ac448dd043cbae10f847b76a8a20ce0a559bd0f3cba36be6fb50512452bf06915094f7a7c7b1a7a517c7fe3a666249c3368fc161a3932f2d10cd88276932d3d2315ec9bbd8a1511216be52be76d1cc48820c98e773afc3e24181c2666fe05cf22c763103498316ba0759750d575156016a55d457f3a538a4822d1f4dc598d9c9e25fbb0381f2aee56bad06d5c6a1430f3a6fd2b33477e72b8f91a066301dec27e6c9bb69acb1fe54f692ff9b20e14a2a71e577f1f5f7064bef074b0654239599257dc86b12bdec3376250f97f5f005ae534014c6a69ff11c135d18b4dd33c13e4cc11018b7445104b16e6d94b580049efe999a49bc660ce9f8757ea3456c42319d1f91e21277ede209bcb9bf2da1aa875a2c36bff51aeff4e2c01151a0243d5551e016b5e1ef76d8a98443d304604391d823e2248de66f8a0348170e55f5b635d380ccfac02b8fc88df515c0ddf26c4c9d9b7980a35b819aced7c720ebe1fa773e33e84c79dad6f46d3f9bc35e92d2c337a767350d906769ef475cb72fe2e03ecc358f1ee1074f5d620b36480f21255cf596afae8506f5a7b164314cfd890f45fadb279bcb742345ddd9007b4492bde23b40195702ec4cf12305ef29d751e1a31c1fbd3ffd9d29fff53a3dfb371227c0f79f3487ce0e76d7188070768a8ca64021d32ce22f13989dee1c46be72b0d2faacc65a02532940e3759cfd742171bf642d8ad3321c96fb7a6da32a70300226f637fe241477c36bbcf1c01a059b520194003c1f6bb6983d74395fa5b48f914801b01405c4d89b666b6918ca546afcce05aa80dcc4da69af0bfddf2a5460e","public_inputs_hex":"0x2138b0022ab9af3c96b082bbf307bc9e79f8f1401462e3ac1cb3a9913a5b856c18c40bec999a837ec1f06dcee05102acdef50c501e771cef739dfd0a4cac5e9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000211521e0a601b59f0fa9d199e9f861874db5d701a0c38f6d725d9fd8c1f0b53da03219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218625eaefc46d4dc1d14d29441b83268d90e246af546b51272b038fd206edb2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7296995105557a58df75d3a42759d29e124a15ef43bad6b7fd6a9d93d4efda1c900382d23bccbad9ba827179293d23b719de8374589fcad5bc6d2148bc787593a"},"decryption_aggregator":{"proof_hex":"0x00000000000000000000000000000000000000000000000ab6871f5e0c604e230000000000000000000000000000000000000000000000063e0c5faa3697e97800000000000000000000000000000000000000000000000c4edda900b7425ccc0000000000000000000000000000000000000000000000000002befd5183896c000000000000000000000000000000000000000000000004d8f5da040d18947000000000000000000000000000000000000000000000000e372e41542c47b15600000000000000000000000000000000000000000000000eb6fd9729b1572bba00000000000000000000000000000000000000000000000000020aebcd8e4cd90000000000000000000000000000000000000000000000027d1ef6bdc1bdc6fb000000000000000000000000000000000000000000000003b63834a1a171bf2700000000000000000000000000000000000000000000000007d98d752da17665000000000000000000000000000000000000000000000000000218b2af27d6fd000000000000000000000000000000000000000000000005fc5b00c064fff6aa000000000000000000000000000000000000000000000005475acb7f772fc6a300000000000000000000000000000000000000000000000d5eaea21fb7f5474c00000000000000000000000000000000000000000000000000025c5ad7f49b8206f35cbb5b62e5b765b61ee0b49a1f8770bea9d70025c2700523a6cdeffad74e2d17c339a3922f7ef70421fafba18febc1023e82b90cd74104a98902574f6d1c226c706d93043c153de5bf841a134de7656959e544c04017eceb0069aa692b1b09d09bd7a13e5ed5ec3350da8de0eb3d4bbbb261473acd3a03e1f56acf424efe0c6de5bfd3bcd37d09cc02b16d1a369712519dc1e780047008bccad88b1517ab06359968bb78d1f165250eefedd6b57eab508d2953f5240a27b3c8f21fbfafb207bef508a58b51480594683a51f7ea0ab2210a377696def48a79ff7efbaa8e0823f41ad197d6b1ee7ee556998280123ec1b9aaae6dd280edf895997e038d1c1c25a9dc3e528367cd6ddf78257f8f4a4c8c13a20283316c3eb5d11cb539b99e5806618d8b39dba1be4c13bd33f165d43ef169b3b372eea8224a06ae43caa0d921207c4f8a36cdc97347efe815d7f3321ce22eb52b6258a38b98f20205e737b6f61ec9e8a86e5cb149f99b66f85d8a15b805fb61123bb0b5dec773cb3b297fe0ee07c1cdbd49dbcb2961b3969e1607c7518a382930487888e32d9bed12a4b7298a26da1f07cba3368953cf9f4a5c127d3fb11a2477adfeebc6be03f27dde2c51742d449697cacf031c884d94c35016ade6bbffa6a1ded069664af9617665c4ed7f09333f51d61f47a9365621869531df3ff6fdde13d7571858c89dad97081a5d032db062ed586adde96838ac6e2c39cb5d50c316062bf90f0b49fa7acd55e6ba1620d7097883c0c1432d691f8ff8fcd8c8075c631e9d6268bed9ca37f2e49bdcf215c9022b55733861a9e7bb732ad6df58cfd3446e7ec2067b2746836af4f7f89c06f25e697f3401aa322174f68a210066a5b63035baed84e1406dc44ec30e74d91129f27facb96b2eb96dbda62db646bbfaa784d1a5fba7dba608196df258f5020c01e07ebef101e89b91d5dec206ff84318ba1638547fe25aec6b87d674308840cae64a836af4ef9ea8cd2ab455927f23633e086b6f6b741485e76bef2b6cc032bb4e67d1a535f5a810fd3cc9899368676a27a90f311557be62e196f20ff52ef13f86ea9ba08fa7eaabb18c6b1afbb4f7771d605e4b1f2be6fe991394d0e2f0626490f444e9ea9fbd75efdb2a25d56667fae74512e2fc0acbd49afee2b2c23e72373c15067632bf4180a0cdc54e9c9394e7154b900a48eba42ba1f44b1d9fc72128f4b3bedaecb9e70e27ed92a46717fb202dac7e349a24736229c5c0836ea091cf2028b1a7eaa6a876513fa071249ea34cd4e1e27e33cd996b948907ebc60990d5930a69598cdf690b2c2c4a1ae184affe235d854ec81da06447e2738270b582081a0574605536f0f836c368de05a08b39fd2d65450c5c5d6d6cf1d87a7cd5a0a079aead0c9239382526011399682aca59d1ac68ee5c18aa4c3f61d13d2dc9f1940bbfceb517ddbe3d02b950661d24e7ed55d0550eb3689f421b3a2a9056451192059863b2f5bbf2fe06feab1df4d0b2165f90a3dbafeca86e3619716ccf0980bf1fe0721c73d5cfcefd66b41e50aa7eadabdd8c455f2779c3b3398132087261797ac8754b7044232941f4d74818e58ed96ec7f2caaf282f7a531758636d2020f7ad743013efcd97a076ead680b17dd244cb55039f07344e15a1a8e2f38870a29edba2439b0837a103e1a8c00e450006e6b589a654b8ccbefd5de0045c8e21c1545fa845e862ab714a464c0b6e00265beabcbaef383504fcf2c5f80cd7360b10d5c24f04fa84e22c6a8e81696a7d4debd55b2058c64ee4339f7e1acb1c8674f2ba9e03d761ec3bc086bf76ce20afa4cbf8328033c71e096a1b21e3e1bbb980c260b3e581b7f7afe02b1ea39b3b73031d0b96080204bffcbf3a04b43f5365bdb249ae301120746252ac7b763df1d20111dc3827f858fc8b12665c07364f9e6042b8adb4df253af298a3b669077f4aeac1aa8f6cc0b44af53c3c1fa4cc56a075d2857a42d3b05cc24d8e929608bb93e738fd680f4cd8af7e6506808ecef185b2b2ebdc44cb7a9ac2efa142c54b09cd054bda803a047c314060dc259796a51bea1238b6879fdf41ffc4269cbc9859c6220dd57373fadcfcda2548125a04d9447280a0696340db71c34a8cabeaf6636088c0331952ccce04a506c57ad047ad7bb9222907f98f62436ed0491d278b5ed7b273a27601258a9ff54c7ac8d3dbb68cf3f1749e0a4c950d439213e3bf0524945627736e7e8fe7f07029b26979c722849f62eedf78929c852c7bd06c10d5a69015ff5983519c3e0937bc3c825472e519547273409dd5643ecec7d1630979937792e5ed4b7cfaa110c7d87ddb2e600ae1cba2ba7b5464a14183ed799350e4d18c512d14b66266eedafd5d32e1141c543d6db248547031da4097158b87ecb7845a8f659c5c02b9ea2ac6f636f3e3d4015739223049f86005714294ac037d14a7ccdac80e89882751314baa8dda7bcb024504e2e27c6a101a3035ff6ef42b99d56c20c824d839f3d98e3131932867267d947c02bb2270046b020798f033e718352799c0cf9d26c86961efbf43562dc263b9d250e36aaa19d199f1d2789110fa14b42d0cd40a491ba99682f72fa9b301d08528b0cd55651c7fecb9fc18e4a725043f251aa9b69be5d31aaee787dc8771fbf31252a90ad86466fbc0eacd6a4cd0d6b94c53ab9fb4c6398b68c5077d5fda03d7e7a1d60824bd6a0859b7fd17c5e3ea922c212b33b1b36a7c5c060eecdec697ba38c0f968500d89f9543e48accf3511e6d0fbb18f089137a7db279c6abe326dd15532f7ce125605cbd676ab45449b2ac04d190420e48f1c0a029eda9944c2b651f681194348f35c5946265da9ae92238bb49a90f7a05e723b185bf8083ee7448ec9517320c5f10fd917b0375e3c88136b03d916220b42d3ef345c9617873212e1e6d1af9a175a5da49ca79114ab1bd3fa654bb9dd1cb9a287c2278f367cc7ef0e35d064982209f67c25194f6d480bd1af6da9c21e590bf77f8e556bc82b3f36629e51ba0bd9e8e8f2a59d7bbbc20be61ddd3d78efba879719d28c116762ad44f7a1c17212136d31493bc280107ecfc3e7f56a3155e6a8dc95ac459573523c5db8e9726948905e785fae860f81331108d539f7f1b8b4c914936d1a06976787a461aed10fcc5ee13a48ab03e06c2eb6d80964b9faad63932663a5a02cbd28b40f159d3191fed983fd4a451dfc47cf6bc11201e2d2faf3049e8ebfb3c7422ca072136f3294c96e6a0fd7348adc0080aa0cffa5ae817a64bf74e78406e6f12e2ce53b20f24795f8d35edf71c5de2ab175685fab6f9c73dc06620bda26f67208c9774b7e52526e6da846f50a867b53b0c964535f5e52c14958463d58d2417c74b2a25d8012d22f20b89f69d9cafc3744aa9a3435674cc2d23c1e68cce4216211907defcc128f00687ab857061bb9fc3fb5f4d2bc70d8652f2f9cf0808c69135eab8fe2b05192d7577511195d93abab820c9f30795df0b10c7f55de58c03d19139b28f5d90128f7041b76c81e6f1444d47642da90ad4e2903cac9481dd31dec5947d5feb56114e0d1865a7bf262de8132d41340ad3aa5e1938c8692b7d9e6af1633d74a3a21d0b65ee6e74bc543b648cfeb52beb7fc0e500afbeab9bdb8a425e43efc6e0ba03f2678dbb80015852281938260095069eaeb25fcbd581d8ebd64babae79e41d11efceb26339550bbba1e36ecc3c91f71ea9f1cd23c0ca5036758e74edf7858e14ad89c7f9c8f71c3cf32fe11c37f583c932bcef67203e999e45700d3a5816870afe8a87a72d9be4d639fa57feccb778e06dbba738460fd0f511c0ad977dd06206c54e18c4a57066e49e55e207d36107037ccc095ec6fa2feae81aaaa44b88370906d542c020f0d3b0e2d80843567501f13066782c96646ccfbe031283544962216425d07ad1796b75e2e9d402062083da2d671d32e1c34e3647bad0322067911656aa8439e56e08c30a1384877c1a32e69c3440d5a25f687c175239ee6cc75c04d11f5e379d21a7e8b32943f9772db2e168f4f1b7b087ee8b7119fd1f18aec2269e83608b1d071924f9f2dcbbfcd070bab6d7f5a447e3a3da752065677b64921849ccadc866212b4a74dfdfe4b8430bdb74f4a9f17a6a99495f0886b442625f2547a6f4500d0dd6f5416d1f40310b3fb8ca4a72861597ffa93f0f9c8e3955fa2bf139bd084522a6726933ffd9e47077365bcf03a3ee29f99edad41cce14458f0684554a86d665240423b236917bcdb313a210c1946d234dd1fe542e742668fd0d64b6ee71070db72111e430e1f27beaba2482951428015889eaad1482b4c2b3157c8eb633ce89bdb8cc75ec48b40e2c50fc5c46e897efa49a7e4b535b16dba729a619462465eef8f964af5497553815acb5545f74d5d677d2c0c1e339416b9c219e50a898ee88e1fb2f1db566e9696f253d79f68772a0aecc07896d2e49332c0f18fd89635440b49b7a80d33da8557759c2fb146fb125ae93087fc2b6749e6a0726f493c7ea11b9d67a1be2dbf04a50105d2b489c75a2efcad8658fb92521580df1b992af777cb0e3ba2c825243eb0e6bdf3d0a6978d1411104b59a46f0bf720a79728ba37648d5d60c06f92608a4dbf1c99fc3e449de7549a7e50762d0232c2b116994593bf466bb0dee85010662193d8ec2fd8a25ecdb2a7b34f7478aed831b3025e984f0ada44ea0333d2d72380d11ea5c1b5db3d182548eb261b77b13181f48514e3f03784963faaaafe860688661a8bbdce565ead9184b182a9802311d19069af44ad2e08496a94d229f869f5a2830c420d4e1bde78c230d8da4384b220c88dc1324a1b82f54e16647c431dd5011a1421c785e130013cfd882192d72f01374b6f2b7f6011bb2194cb772e337033fd01038f1d77810506f0f93aa4eae822649b30fff4c315bcd99b6cb7bc282d60e8aa24fa71bc754482ab58e0d721c3c2ec839f0f8b1c83585fe7ebc00368d3baa4a381440565216c8d2bd04fb96d32311649b8a7a3ca661a0cf53114a8fb32d33cad95318a6154178abc8c06440e21d22e5c70296141521743a8a37855d70b311927b84716de2f8fc092c91eb3a7a1f221f26aea2f88548f3af4b19fc475bcf49786adfc8d7e7349e1693548f512a221f381f9587f1fd3cf3cd069024a1170feafba8229cebb8923a7ab8fbd856196217b589aa128af06c775f25ed9b3aa9bc23803fa5965ee8b7794206585ab63ebc119c919779bcd9b1e024982c6fb199b1679c9af2da8f200348f68ec3b2a00c0f17a15318a649ae59bada674e3a149bb1d6431461411e2df3e2aa1958b722048b16a07dd414de7958c407c3eb8c760779358ec1e2439b58b8d00378bdd2e9e9450de9e777da0eebf79d558d029019a16d1f8c076fa5294863dda329ececee07020721d000c002b15cc3fd3cbf0f0fbc80d75c1bb53ae1b7a244fa507318c57e4c2d6fafb6038ee34355adf14f0363881911843ba3c655934688976f48ac38ca4e162f5b94463b38687726d27320a2d8c97ff9d8a79e81261babee9852ad0958c210d8ae1fe24253e9229b410ba1f11ab4cad40642dd7c818aff33430752c5f36205ef43d3378c9968b0b16a881404aa643c3d555f84b78446cb9bec133cbc10ad00b9207a883ec2d82bad1051a9c39453d1b63188f2c5c052643e597db86bdd1621806a9ef2c04e8cbd9fdaba392d0fc997cf5a49811bb4c8b68f104ccac280541ac123db803c502457797ba6ef0da3b43641d8406b78f1007c09560d45062a65259bc7636f785729b40176ebd0ca1c6f2ffdb9ef2915602c4a6275ac8fa7cbe71adcd397d6043297be672053abf8339f90c137a367ec7d6a782a51b8285f63721916d859797c32299e9413788fc27175800859f9bfc7d3939d4f6b5cc9777b2f198710723aaa5fb5f57450a5ceb88a674796d19ce70fab58e730240326a016922b06a453d8c9f93c4f6a13bb87c227a297ba159e626f5823114a76cd7b0f39410cc25f0afd48083c62151fbaa1853b27d7a17fa1b9e2fa28a284200bf12a6f5a2f550ca3ccff9b6327e4f7d9983a448cae3e7f9ca4e628df133a58dfe58d741b284a4e0b987dcb8dccd1f21874cd434280feb0e942f8f0e5ad8fed96b73bd26f024f4f697877b9a2164985542d2969f52a5b57c433eea4f07a445aa9e833a37f15dc67773cbb58f86cc70a1b5779b019ad98af907b00c0a1fec4492d26e38cd72085f1cba3e5e9c54abcd00c2108dd54aef936879809260609e0787ae4bea1f618a9df278efdd7f15dfe9247dc384fa4f971588fa356b4e67377e8fb6251408f2b82baac18f833a2875d3bc642a5838432ce511b38005fb7024bc01688ef3f670da2fd6a5794ae972da048893816c19549b73421e0d585751496ed222a7cfbca1d415320f214e7cee462d0689ffc31bd05f4c9a5ea3b1791bce9fcbf374d2d14004ca233a4b174ab409e968d6399606527b624923f381eb8c17b2805dfab7cca280308a2b5af4f1aab2d05e78198ee4536f2deebeafec0eebb33df157fdbbace2e747e434240c5cfe49275180859832b2d69923bf08c0d597d9112eeb73568c91fd8ea19778ae26aa6a872c78c89c957d2518154b689bab59b2ffe5bc04361ae131dd276df1a28b2e06a9df883220bcf76424cf289b94d5bd90056ca2a6828f210f1ff74decbe9a8961ee9c5963876aa8face86ca89e9b038fbc5b1ba5bc962c128107f963cd0d439c4fdb465eb7834c943f21c1f3d46a7f057b75b42aac8c472a5c5521abd8d5913f59e4798f9edd0bbe643ab68d2d5f2d4d7b7dba52dd5c8c01fc9c7bdbc80873c54c494f37b6f6fa4536f37b101a16a7da7ac943fe0f666304c7a6659b382bfb94977ea2f22e244f5224369d6025dabac1e08614146ee2501ddaefc72b74b56f7f72ee8d908bc52a354105655e85edb6dc768a83f3dfc0a317c66db9a34532d5f7356579f0741dacf256f0af84798ee17836c4a40fe4b5cc04c199f7039d38a4bc5bc7f2d99fba60a0fdca779b92f02ad5aaf76f1fdefb091381e6eb635e8634516faf93dc50ee8b484c07b917f28d75a657b00a68ba0b71015191755b4d819437281f7565299d9d5ab193750340c3436c4e1ec8af65c201101a107fb877fdcdbd711cc0e888f6a3918bbab8780e9651d6c8bc29d473a25a263d53cc7805cea42498373014e822341492cb0b5846f3651c4de21d6a02b449249f136615c3fa59efaab74793ee99dea1346e28a861afe2f931757642bd3ea028fac43df603f0eef3eb0387cd88048d715e733dc835545af0a970b030f6bcd40739b526796af9c7636fc1e0023beae25886eb1ec9fb69465f36cb8db0143282114a980ff547ceae0ae0328b0a2ff83894cc7efb1d8d3268e623e20257143ddf1690c3f89ba0cea9077e7448601c66a68816c5d7adb596e9df73a9e7d4f3b5151e8e6dba9f96d00681e644aa6cc33f2c88c76c3f204f9e0f4abe5667921cc5dd0a77e105a39ddd0f53525089e44c33468ab32cf7761380760d7c24966908f7291f3cb7b08e1addf167d9a5eb038f1f433e711c6e67adc478606f09c33400928b09658bcc54c224cdca2dae3dba6278e91f8a416474312cd9325be5c38d7f5d7e07f54faf13c87c1b95c0f7f21f9f879644988df52091918a8fb17defcd05035b2c01c5516e3c3a8cb16dbfc84ebf730cc91c289ae1d9a2247ef46867c4c3f8b214c7e231c7382212bcfd3bdfba84e5befd2d04ead43d97823562f066e832f1f31e830d7e9747675bde52ae766e1b6f1fd1868b78f7acd5e595aea09c9dfadbd42088b2218775b734708929cd68d07da0d0544236991c2b7cf3b1c8a535fc2a741e04a56884e7fec5c8b37e770b9ce037d6d9e5963f682452e8d786a57ea1ca4c11dafb71c383f1751378b133a730dff48da6d638942abb532cbcc712975bb260159681bc8d1480de29c8d1791ececbebef1dd47e7055855bd32ab876af784fad1175e04f583e93f827e3336d431ddf5f2a9347290732acb2c1e70b32aa39a1b61535d18522b8e335ee209aef0c81c3ba6c2902fb07d3d35c978a48c6242a5c0a0e5a2a7ab8189202cad4eef209e352db7c4548e813f6479e5ae2cdb3eaf32b601bf6758cf1a0678a0daf9120dc0fa7c4a30f5602f2ae2cd64d49f6cce7de341603a1e9661d5b7553dd96174da8b0763cb968592477ac917adc4dafb94d89522c29bcb39fadde0390e904c2638779567407ab30dabeb7f8beb0b49947dc9e8fe7291197bd5ebbf948c0326263c7cb67a772e3ffefa7d93deb6fe34c83db575bd913e74272a40222380713812899c64497ddd2f0ffa40bd9435ccd8dcf07812318062d0ce0a9887f24c623352f28434512a3f02497d08f70e2acd92c6f9c7db9c70ce84edc6d0b2e6a85061ecbbb6d524d77900e545869d585f02e66c11c5683262a89acb3a1d01fbc647be2e4ff6850475f86dbbf3a5533cddb04f9f759ed3f8c1a58e6111f8ab44f6eb753ce9b76b08ec2c1ca1e8e4a0b12f2468685e97514f80084f9ec72296c13c390174cb7058a1cb652524e152af41bdd9db80f4b26159d019c5915c863e55429c22b5df53f3c2c708d16dcddf9ca6144b3b12c102f6e4726abcb1e662e072858dd31ebcb6fec808ae3818a0e1529bd7f967ae9e4965f942953dd62008a7880ab0f25d1aba340e932e7ca5cfc654d05efae33677e86e73c1e16c255cadb04bfeb1f46d2a57eda2e9e0125c6a25e611177db2f81b52e4ac6270c29e8222702c6a2590dc3853e75a6dc26aad0dc20e13b71d273946564d9d7258d3a80b86cb1a2b655be37f8b0f78265f6bb866571b384a0792cd7ccd6f9f61514364c60b0d46d272ddf70cc26a62f1132e1edd6f617e815dadc8febd9a74e2e645c1d5c5e21b5c8747ef39578966822fb78829299d4ffe3e411f3d3bd5f092e06ad539341a69ee6302e31511830369f8bf22dd7204099269cf871cc0997191f1a2d248d13fcc11672953d9f5ace68497ee899bfb32b4b7bbeb46047e4ef821402516b83cb78caadfadd9fc6c12a398d99f1b878ec66b515e7483a9a0cbccb083041b2aac57d88f01d6d47b3ae84186a84792b52151c25f6587e21f8e6b07b1c0fc000b43896466542644603e14a650e16686d853e62db267e023569d5469c0809a8d114f1007b7827216e65fafee4b603e959641d11636efd348dbd46ed560624ef25c04f501716ef93cee02aad775bd9ee6919852491f3d29b942372e1882085117390b7aeab2e50367937357f59b9f3a24d1c14cc6497dbc0818fbed5041553c7bc5740d0e9aef2bf62243c1ca12f8567c9d3f39a40110770253767fa7c26a871d60e27b75d9e142b1162a4130343e788148124d712988045ef96d48f8920e88ff5c9f60d09d2f77ba9b403bf6c6d0fc0799048710792a96035c73a3e450c283036736b9628210c2497b080c5abc5372666768ca864d18a6f203fed35cf272622ddb9a3970878f471c80de989f90ebd8cea6120f8bd4c593763bdbc5a98058b8395cb3225c7060bb36acc2d22c0338edaac7d75befe39ac4206479c86fa237ab01ca34b0328eb6699049f29188e92e7354e69dd727f960802fefe99c3d80c097dd8728bf5d5825041d67e5ac9858d748bf30271341377176ee8bca796f60e5c92647f6871a1579155741c7b634c268068d9941eb9acd84569018e4de82811c568bf95b24c04cb3cda2a83b14307e668bb54db1a2569360d0caae00498f91e0494092814900d31c78e68f63f06cb09a782d204a10067a78a04801888f8b707e647e4d114ea7c1e7faba4176bd2977b7c1d0e97d6e3ed976c66930ea8d1ea278f3899dc95fad95147a22de703ff82865da597000525a1bd0656d82a84f5d2255bca0b9bef6038b61f0e92a5ba1395707daa095674120eec99fc8ac392eb5a178588131cc52f9e6d45d766712bb3eaf094693a5af7a4f746175bf7aecd09831d846931480245a862576fd3a006b07b1fd9c2db51db74543e275d9e7cc26f2d27452fd95e45041aaedc81d99067f7567db1fe9759e84b4fb2d1bd93bfefdce805a6cabc48654d9d38ebf014ecc33eab6dfe7fbe12b4007cb490b235982a55a611fdeb14cbd17ae02f6dbddc8b4ab0e8209312dfc80292b4c072401ff7336ce8055b3fba6b7058057342f5e55266f9bf87220d9c9ac9fe0853f3d4f4d019d829195d64b5e10165b80751e8ed7945c9a19a7960580b7f3a9d7a6065ce6a26fd3128a6e7e2d8d168db7ce213fc75b4315145a583fdcab1de9a71a41fda973ff1490721ae0f3ee28441b6a46876cebe7b6d692d551bd2746bef1fd28623c1af91c020c7c80ce66224b03e7b9106196f94b8e0c9b5ed67af49449aa45213b412de6e24c842e747291b84fa0553bd0fae951fdf6e70d9412ef0ba752166a5dcf09ecb079b9de21279373de98b9ca059e22817390f90680d8d338d7e35d0dc81751a500d4bd7104c7cc8e52af19d74caa3d6928ce9b0bca085889fbf59a86959c2dcdb13df2f80658bacae156b7f1f4865db24b07fbb6b27942099f9d61e57ae43c3c723bfd52acc8ffaf4fd9cb1147322dc31f7ec5671c5f0ca5c5155ed6d9f2e2413248241722317c262c5bc54875d886f0d90780674e073c5f7f921a6666e3048cd16d5814372e0236fe69a63a4f7118d7eb75bc4465dd01181c9a197ea72f8307c2841f6397a9baab5a97fb04e109006d8127d604f0b7d6736162c40bd8b1c09221e0922d2139987796499a7fb097c9d0a4671b898532936cccadae32376c93dfb059ad2915af4a690d40a516c72d74ce5d4ab9e752f58873ea88227546e021f701702aac2d40191a410dea52f40a4bb996be8002e1c57413e0dea9914098f8a880a8c387b2e3309533a4c07aa51444956ed8fd2a314017814af55da77e40ff7051641fde9c392981a5e7d779529be3e0be0f6890bf19b24f53ebdbde0faf9d69f10e9fe5c469cd99083a9c572eb19b940f9b0e8094a75fc98a7131f2c923408620f3d931493d5a7f759cc6a21edbe9dbe770a109672574d8bf6aacdd48623e833296a76845bc8dc66f9e0bf4d05b889bee67c4c2852750c30d06903783da6ce172c02a8f8653d8211beecc345dc19b6f7cbcc803d66ae2128ba1ba055f761ca3a1aad5843b15c067428741c224242e5c518ffddc45193b3a5ecc922cb13c0d0a72d4130a3f278c1f463f66423e4710027d0b319048abd0a6fbb66c195b9d1452e2e0c7c0e8374b22294a2129630e2cc3dea0b98c2c13758345954fa86eab6ab710a512893425e0268e10b34ee3e2e6a4fb03040687698c97982e30bc2a8a2b2fd2248da56fa8f2105609a497670832678fbaf89a7935cf26768c2c03f443fcc9012eb0427bcaf487189c20e24956f34d23792ad3f62596d3767ac07ae38f3fd4b11324800ac6e2d023729dd5df77dc4e0cd81d0ba8e10e90a266711e69d577bd406b1e218645fa2552bf747d0d1a87fd66c7644155f6f5cba9115d114d7631cec08770d53cead9762e9eb24399c4f97d98fb3c365d158799be00cccd3d20c3b090b431b0c2f7b7c2ef333ec898e469fa101f1adf6f73815f3b09bbdad8349034f1f90f27a8046dca9070e149c1c23150321e612756a0c2c7942d7e30059be4908050ad08455affab49f27dd02ec5169cd976f4567515baecfbadbe97c382d3f1826774b8c096b6862b740081c523d47bd0b9639994b4ec95ab12845086dd5fd482538707df831ef734170cf55d329490aa2e0e49643922241739793a8c75e7386283a026efc405fe0598677d246226a3ece5958e0d48de439e944a05fc643d0641fff61f83de97b677bf4840a977ef5625bc385b7591755fe89ee851ea5d15ebf2655014e914e878ae7c1f8282c6189ecdcfd5110178786f7faa3b05de46b43cf17e113d1492df5303ceba990b322420dc3220d8d4415f89381df54d5ead445821656c02d97585ac6f793d80d33115e53d6415f05f0c5d90c3d77c3d140226be02a3ee5564c70975456bf79d426c8c33efdf706cd178ac3d687e28e4d2204547d0fd5af73db10f93e0b6c523b4ef081426af896697aad46e292ae0c5fab03ec3d0d8dbfff9127ba2e3c4eb3e7a55d92890674bd6132382df800faf6b8b407cb5e2f34f902cc48285bc99e308f2acf715a3b8f884aa21e144ea9fe2a36eadfba592775d95bfd62c6d71c3089734d67d08cb00dd85d23185796cd641089a93e19b12beac08125be0a38ea27cef99c4cdbeddb4b278caa2fb8d47e2745d5c09e83222c0efa0932bba4cb4546e28667c714e5b2b974eabe47fb29b3f78cd5b43742f101e475b51ad373772e93166104a79b4efb175dac3b442b52b9504c88304419102b169b8bacf4d47e97ab2c69e9f5654f5a0cb6f55d8fea831cb665e93bda050b2ad2bee6223c4f9377be451cb1bb4d7d5445b1eb9b58549ec07694f34940216118b0e8add0f6d3ff6199052ea7668d13954c7caa2fe6af1663263c9a6210ae0b01981a9f0fc8d9d2eeb8d92572ad287146f3bf0c20d23de8d08c40c78dad3d061c8102981be8ed68bd6f3b7bf768c40b86a06b6da762153c82d045133d3976a50aa6637a1eec72f4f886a043ee57a4e6ecf52067f7f1dd512d0829b36989687320fec9da648b374ad4e0247d1fa97700c286b7e1103f696941674e6f3a6f9ad4223aab447b6b691951dcceffdcb30f047653433c4f8a1abeab791b5ac76b18502575e60cd921ee2346e0ede35620fb30907dfbfa218913647ad415c9a48ff09305f729f2bf156c6478011766cb094981c086bab98c384f67a7dc579b811ba5c11f607412b5d8cce667aade35ed4efee23bb261c4f278e09b257d502bc61ae48712daae64de5ae2bb6d679b43fd9669b02023aa3eb4d01d10c4603bed9416d06f16bc522446aa35b063e490767fcc90a7bf197281c5c295c1e0415dc27d1e29df06d659418c6c2d19a198517016a3c76ce82fab8d540e656ec7170093c80446c42bb2ab499e9eeed746759a7814701b945e602522926c49aef0d217ba7f3ec0ac1495c4281a7b4a9e1464ce6c97788d617101c912e7918be268957e80dd37fa1c1daef5d845aae5ae93f3d73e13e95b2f974ec218a863270fb89a30f0a81f70f815e9e11d54842d2997758695e9e919c49ee9568970dd985f95ad792c4de69c602ca2a090660e70cff6f75b308d6b58fd3d41bf6c2e1ab5210914a167f161efb208999866e918d0ac040afd7f314e279aea6a9503c0fe69b94c0596ec7204937c282c824f63fa7641a2732762083c6fd099f8538f33fabde31df0ff298e4d691403845eb37769b4a7e325f7b4b90dc138807c7bf8c94b3308c8131021dbc702ec1b0d2773d0d393b5ee72fb1b8c46bf5a2d96e008f0a27bd052c6ce663df466bc10b34b779436e65c9da5839de588d9356cf64f721915fb81cf1107e5861a4fe51ceb29793e3bfd641066d690ab8a27bcd93604040376f886a2bddf62b99aa21012f03a25b1808210494fbfb7c5a6e98c9b0183db9d9366514708d725bd15d6471c37dd3530ee3ab502f0bfaf4639574de4088216596534660c852c04f73e77270a40fd0514c085057ceb30638d46641a2429e8aeb06b89a01c7a19bb9287955c17d5b7abe02aecf3f5e497b8ce13ff4402e42e044c3d270c04db487f5d00f04a0697b0af7a5e27a2a7c04d5bbd73c3e91e2ba020b861cf43676ed66ec9c18f4129399d25127fd3a40f696bb6dbccf3829d8babd3a13e6aec6f0e6bfa632bb90b26c35be6ad3e9fea820c0327735cc17a5244802c9466dd98739a06bb34e742dd044554adfcdbbe8d300cbc39c983ac1a9222513ebf33bd79f429c47d58beece61dd0536dfb22b4ee0b661069eeadf37d8c1456b05f3e19ee3e058c732c8d1ba62a6a39994da45c80490e4a53575e6a739a01d8817ced669ef6dee1dedb34984b2688cd26b1fd6e4ed748d8dba93b6ee4a21493066c1a10f7fa44f50a02206b342a5e15c483ce678c3f87fa37ae6701c4105ea18957e330b13106f6d62f55dd9e05f880741b3c98407fa02b8b956a0b42279f01abf85630fbbe613129d4a710020602b5ce04f6a3eb5c329dc34aa10af6d222c111845bb6016b2cd69f48e4edde14106fe41edd0cc43ad8800ca68c5aa644bdc46f64654b3fa561e10dc84c4612059e79b06da8e2bfb580c268e0c94f02625b1feac968586930f5fa9daa1d52e2166bc02b21f5b5a51eac5219ca1c42b6f563ed338189e34fa6c3e8d5922ca880062f1a75d8d73e3cce28ccd91097acfac61ce220ced87115497eda778f752709011be2b3aec8c33879c1b7d9f041cfea2e9f10ec121a0887e278396eb143953a261cc5d74697fb31f3b525f2129e9dce7542e906372204e07e6d68f59f2bfb9d194e059fc2816cc7b5faab72efde88c1daafb9dce629acf1bdcf7516b7551a8f0d427ae711881bb9dd56f6ddf46d96644fd2e7bd577830779ac1e706b6dc298e0b89cccbea03d22a857589fe4895f822cd5c5fd1634ffe6ef44b7dca09e57cf30126afd120fbdc1cde39aa695bdce2ca770926968c345e801bac05c163e4bbc4279d02daac4bb1a306be1941d646c5e93050adca4277432645be6a4ff50ddf5805d1070e4775d2d6e006453d6b67e718f8289e49ce80b841212e613e505452a827677548ec16fc965456db4e86d45b4d59be76f01e4ba348015b12e75937bf20","public_inputs_hex":"0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441156615ed204aa948509f830e7e8756e609e419f8a6f8561fddd9202f8abcba0101cad4adce90c01d548eb5a88e3935668204c5bddb827b618a40626d8bc1281f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000203219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db70000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}}}, "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 index 965a14e31c..d189e8d124 100644 --- a/circuits/benchmarks/results_insecure/integration_summary.json +++ b/circuits/benchmarks/results_insecure/integration_summary.json @@ -8,164 +8,164 @@ "operation_timings": [ { "name": "CalculateDecryptionKey", - "avg_seconds": 0.109839375, + "avg_seconds": 0.115728250, "runs": 3, - "total_seconds": 0.329518125 + "total_seconds": 0.347184751 }, { "name": "CalculateDecryptionShare", - "avg_seconds": 0.613667722, + "avg_seconds": 0.608609847, "runs": 3, - "total_seconds": 1.841003167 + "total_seconds": 1.825829541 }, { "name": "CalculateThresholdDecryption", - "avg_seconds": 0.567017042, + "avg_seconds": 0.578625417, "runs": 1, - "total_seconds": 0.567017042 + "total_seconds": 0.578625417 }, { "name": "GenEsiSss", - "avg_seconds": 0.12360793, + "avg_seconds": 0.124242194, "runs": 3, - "total_seconds": 0.370823791 + "total_seconds": 0.372726584 }, { "name": "GenPkShareAndSkSss", - "avg_seconds": 0.224165903, + "avg_seconds": 0.223503888, "runs": 3, - "total_seconds": 0.672497709 + "total_seconds": 0.670511665 }, { "name": "ZkDecryptedSharesAggregation", - "avg_seconds": 8.543418416, + "avg_seconds": 8.568398333, "runs": 1, - "total_seconds": 8.543418416 + "total_seconds": 8.568398333 }, { "name": "ZkDecryptionAggregation", - "avg_seconds": 49.652658458, + "avg_seconds": 49.047040500, "runs": 1, - "total_seconds": 49.652658458 + "total_seconds": 49.047040500 }, { "name": "ZkDkgAggregation", - "avg_seconds": 20.662634083, + "avg_seconds": 20.151443750, "runs": 1, - "total_seconds": 20.662634083 + "total_seconds": 20.151443750 }, { "name": "ZkDkgShareDecryption", - "avg_seconds": 1.446775729, + "avg_seconds": 1.504357312, "runs": 6, - "total_seconds": 8.680654376 + "total_seconds": 9.026143874 }, { "name": "ZkNodeDkgFold", - "avg_seconds": 78.077101958, + "avg_seconds": 62.889247500, "runs": 3, - "total_seconds": 234.231305875 + "total_seconds": 188.667742500 }, { "name": "ZkPkAggregation", - "avg_seconds": 2.185247625, + "avg_seconds": 2.156797250, "runs": 1, - "total_seconds": 2.185247625 + "total_seconds": 2.156797250 }, { "name": "ZkPkBfv", - "avg_seconds": 0.330690194, + "avg_seconds": 0.328596097, "runs": 3, - "total_seconds": 0.992070583 + "total_seconds": 0.985788291 }, { "name": "ZkPkGeneration", - "avg_seconds": 1.336457333, + "avg_seconds": 1.329930791, "runs": 3, - "total_seconds": 4.009372 + "total_seconds": 3.989792375 }, { "name": "ZkShareComputation", - "avg_seconds": 2.652245451, + "avg_seconds": 2.693458527, "runs": 6, - "total_seconds": 15.91347271 + "total_seconds": 16.160751167 }, { "name": "ZkShareEncryption", - "avg_seconds": 2.472213376, - "runs": 36, - "total_seconds": 88.999681541 + "avg_seconds": 2.489975329, + "runs": 24, + "total_seconds": 59.759407916 }, { "name": "ZkThresholdShareDecryption", - "avg_seconds": 6.197666847, + "avg_seconds": 6.047533777, "runs": 3, - "total_seconds": 18.593000542 + "total_seconds": 18.142601333 }, { "name": "ZkVerifyShareDecryptionProofs", - "avg_seconds": 0.098564625, + "avg_seconds": 0.097465083, "runs": 3, - "total_seconds": 0.295693875 + "total_seconds": 0.292395251 }, { "name": "ZkVerifyShareProofs", - "avg_seconds": 0.216449474, + "avg_seconds": 0.226985783, "runs": 5, - "total_seconds": 1.082247373 + "total_seconds": 1.134928918 } ], - "operation_timings_total_seconds": 457.622317291, + "operation_timings_total_seconds": 381.878109416, "timings_seconds": [ { "label": "Starting trbfv actor test", - "seconds": 0e-9 + "seconds": 0E-9 }, { "label": "Setup completed", - "seconds": 2.979362292 + "seconds": 3.041689125 }, { "label": "Committee Setup Completed", - "seconds": 20.254983625 + "seconds": 20.243337708 }, { "label": "Committee Finalization Complete", - "seconds": 0.006196209 + "seconds": 0.007484375 }, { "label": "ThresholdShares -> PublicKeyAggregated", - "seconds": 379.382091875 + "seconds": 304.504600792 }, { "label": "E3Request -> PublicKeyAggregated", - "seconds": 381.9183135 + "seconds": 307.024598667 }, { "label": "Application CT Gen", - "seconds": 0.3119425 + "seconds": 0.318660917 }, { "label": "Running FHE Application", - "seconds": 0.003318833 + "seconds": 0.003694084 }, { "label": "Ciphertext published -> PlaintextAggregated", - "seconds": 80.313326166 + "seconds": 79.271051417 }, { "label": "Entire Test", - "seconds": 485.793576792 + "seconds": 409.917920083 } ], "folded_artifacts": { "dkg_aggregator": { - "proof_hex": "0x00000000000000000000000000000000000000000000000e1f2dc40db945d42200000000000000000000000000000000000000000000000bc38cde1aa22cb5fe000000000000000000000000000000000000000000000001d3d59501c65c5e320000000000000000000000000000000000000000000000000001fdb65cf5613b00000000000000000000000000000000000000000000000fea025eb701a09f610000000000000000000000000000000000000000000000099a31d5419d58c50a0000000000000000000000000000000000000000000000073ab1d4ec48035430000000000000000000000000000000000000000000000000000238cec0a15743000000000000000000000000000000000000000000000001e876fc999cef26f50000000000000000000000000000000000000000000000016ff1d86d471a44cc00000000000000000000000000000000000000000000000be45a89750c5a5cb80000000000000000000000000000000000000000000000000002e6bec9594479000000000000000000000000000000000000000000000003e285c4315d7c37980000000000000000000000000000000000000000000000045c3be92a35649f9f000000000000000000000000000000000000000000000000774ecf2be14f05ab0000000000000000000000000000000000000000000000000002b53e01a9484d028db3b0372cf70506ceb36d180fe176feaef4cacd38465840282d05d98c83a126caceff591ab92e45fa2a8e93cdc4c9da6620778e8e22c5b29c868b75d9b6e310d3c31ecd03d3676db23158116188c3e53d9c5361beef5528604f875d47f6430da4b0162741a4478a6993c322ca93eeae2162c546adf69e792b22ee7d40fe9a29721ad2ee16d01f9b344c9dbcaae3c3ea3c5a09dde1dd269275f9cb213b601b1bccaf864b9cf3cba884ab06b1235ea1ad09d25f9f5ae4a31d453c8a081af6f71625c44567b2fd9faa5491cbe7332c645a24f9c9c948f6fc3ff79f4c8cbeacbd0695e4561a8b7d0b92761edfe763e39983b9749e2cee9517b2f80591981f8361072b10967127b862ab5b83da376af0c1ce237a9a3a17076f970f9b5fbaefabb21e6b66500a97693693d1b5269a3f172d2b565e8fd454e200884091bc9c0822271de3d2014a99fb2925abedc2d016d026b90f03aecc9beb5324f29979ea4a64d4058ed291ce1c39e1d4d9435d8831edea733ddbb559c3a5a97baa1fa02fec3e5c252513658656267eb506430a22753510795a9bec9154b78c5732be8217ec0dc82312dd0f50f7ae7173242a014281649b0ae63ec26096d0ae531885f0759ceb8503751681ebb1062e969d66f1e5e7cafc78baffb7f8b1a455118bb9e1446520fc0525be99999487ddb1253c1c336fccd8450b731aa3ae847112654a56da7f02a2272b733c9b7d31a2e63a37387fb26d8af57a40845e709ba3c4e1c8a898a237a41d0bdec5d3ee7ecc282adbc192dfbd6a55d36de4930f40667fdfdf1c136643b9014bc9340f9748760531e6eaa99075b60bfa8efbcec485bc643cbd1b78463183069bd6487a0fc8172da864dd6a0d3e47fe3be391914d6c81e329bd2a764f47c52f4997c3f2a8430ca679c99a6f0e1ffea2fbd7a0492d0ab6cd393449dae9dbfa2246c5afcfef78a77f0bcc680c1de1a8a29f3fda46eaf9a7ace14165cbc2a076126629fce549bc56da5b7c24d12bb9e3e8dbfb356e24dba1f622793345b0dfb50e525c6f6daa65286edbf55e9f5d56a92e82924936d882a31c9dc0310e5a8ddb08ac158364c37634bf8ebee1cee1e7ba5394f1e10b2b83d0b1b5ca5c34cab202274a01af3f501c8ea02f6986db0d8446b1827d4fcd2022faa954e78e9aec3bb8186a26ad086a6549d1fec85312e028556f7213e4a725a976b266bad87a7c6b4f0f1cf3ce1ccabb1f11f3ff9924857227d0bf3efc6c5f8316b8a12cdd3e7da4481609dd4d212555a700a26914de6cbd75f7dcc6632915094c61ec6ec24eb813170c5a395a67b0d3f35934478aa0989100db0e17e294fd55702df7ad7f3c73931e141a4c58e29829294f9c268d7510c42675036df15feb6b50c7b831d297790aae0f0c3b75bd3e146d8e0ac2a60fe46169f324131fb647cf4d2b750fc4da9e62722de86b0517bfea16566d87b43dcfedd9f650f5d8333b1774d9d6f8b77c015f122bc9d45ac7c05143beffd7ddaa1ac8e69d038ea603ccc156b780b67286b4e96c11c455e5c1df524c5ae657e746ef3e60c8f6b0da74eb476af1e0764199d7ba633054f2cf1eabf585712ddc151023578d2ef9940601597a7681cb0c2b89d1c4b43053df73189ebf5aba935cb94bab2103012c5bc86858cd001d252d72cb08bbba1764ad88e8370c2f76d3c979a20c932ce5edcec2b3f3c371a97c2dac039c6de9164805143e1705d96e0a10f1a419d7a4892e6e870be740ac8aae4cee4e27ce15162d0f514bd517e1cf13d3436600d54ebbbb0fb1727bb2839790d7578e01c924272bb26dab779a11b0b5d805ca706743dcb200bd6dbd1ca2f0a6453ee396afca109816c66dd6e17030a57ba31b9b46b476312eaca02f732cbfa5325295b450691fd3249e466f3311f99a60d01590c1f85ade3d2f0de3ff9d98b88a216377e5a32b6fe740893e4e5fe67a1c93ef089f631e2bed3748ac5d7b9849ec362b7a8e4f11418c50ec3d14891c877c2350771170f90463e9764438b9e73c30a498cc23d403c209f867cb54041c87dddf14e7a0170db0084921caec1c69c442473b83f12214f4fcc66f1aa3d185c8fe2925f3115dcd1bae3e97a757b08882ca10d6ca5b6b149c499952b188fe388719511ce1f127fc7d706685fb33ee80e774d517bdedd01344339ee00a74b2dfc3511f2d93090ac1314cbeb41c89f2cd14617b5965696e0d18b8d4e3c13a0a661313a7af2cb8c4ad7a4c6a0322837187e5f6de5dbaaa74207144c4471a212ff3cdf337d1f749e3cc24e4241b279e73903989dc24a3057c00cc57fcb3f1709bb431c38a4a97873e91b223c6709f18ca88affcbe7f7428c00b5ef61bb8e71042c3fffc919dccd7c09e9ca069ed1d7bb77c4c1acaa54c51f4169f20c2dff03bdcc71572044b5b6a185f0eaea935dbe0203c676bb6c04b83591ca94a869929dfd662fe0c4357881fff436014d3aee362554a5e1d9be1cf54450bdcb6e51c2e1ec340a774ae942f45ae6827afa23bd8b1b8e8a9b732240c66bb1dcc84ab5611af066b0c61832e7db92acef04757679cd81f94ca1d84020b8c0a2dbdb1872ddc0fc91bbd3978810b6820aa2a336a1d97d74d39e82ca9602fa4ea23816c4d133fb820681076e7cdd6d3bc7d0e5e15a6185a1f3dc60326d8cd8a3314a0a1598892960a9b9fea1cba9fd1d2c0e56fcbef30c274232d0d23cbb9a97a0db15d1941f5a64b0dfed341453ffbc79b7fff1c105f3f595418fcd4de049ae1216484d67dd0d53644f49e42be07ba8ce80fc7a3f0b3e8d72f6deaf93d43cae5201f33e07ce99dfc3b88f89cfc55e50be50ecec5fc7d8c24d189057556012d8113a536bb5af66af2c891bb5fe1a3e7830d73ea7f2677f7010ad0c2df1f11cd1c2ed2eabfd9fb7d58cc1c2df2e34b1668ce803f5f9822b6d309bcda7eefe05b482d6019bd64419ac04ad495f3c5219db56982f0ab2f6d8a5327df9430c549f33d1cba8fc85bd28b2b02b23bbedb51664c20d36cfbcb21980541007bd6545d997d1670dd8db62cb6b238af1c3374d98c4e716693d48e51de2d6d6c92dee172c3851f1c7c1bbe04129d02babd13d4420449dc4c70d788e85d29e15a59a780792fa20d1c823aac167c73513400294f418d615ee959a346fba56b59ef109d519688ec13baf06d5c95775d545cee9e830b863df885663184c817027573b31c611c180e1b8d6478ebe1cb9153a24568d713e17148f00e241c5ae94278bc3808c18f96f90699f6e4d7d08014e0bc172ef673c497f8f7c4b899287255b79a0ad7e995051c2aaa0d6c31dc0be7550c9f795ccc0fdf44f2f7c6fdfe3be7b5f3f0d477768b371d1f8f97c97ed109c28c69d38e79ab3203b42cea09d33ced7755ba8d6ef6f877206cfb2b1c967ae1789012cc8ed894d6fae2e7cc2f49c797bc69f40c26f42d7c0f1fd1b8e02dea8d9113c1d96b08bbad5c3b653564840206871aa2bdfccffd6824826e74f385e5df25f73c4adc48ffe8e8d2adbfae9bdb911097a8ba4bf3ed9426c46e6750eb393149291727a7a207844299aecdd9af420413435e676f83bc50120c6542706abf0783d001ac68ebb33b72657035e4abc28f1e2cbf8593cc87c60ccf030125853b79419c3f6aabbf72b7a2014a35dcdcd07446bd08731b7a7110160076de37150cc9af5785ca9007a79cf551f3897eae9a4ced3307f204a975650beaf97b69d70a3c471cf295fe0bdf4da169ecd1c87c5e1df7aa38d0a8a89d2b2c4ff73d6028e7b321787cb5c6845264044ececaa3d6316f08169beba505f03b0f371638b194d13d7bd52fc56bad6242374cc161d5a74bad7148a41dbd49e44104c2336b17615c92e8a9f47f813dcd15e14ac26b160917e4e8b6150a9e452ce9051562ea0695ccfacac02fec03f930736506585b5876c34cc0f3e8a569a4f9a82ae3890e9ce939ae014d8699bb8c52b878556f61d6b28d6c85919a2e323b8ae20887e49e89bec0daf0656c9120e9a96ab1fb8a90cf22093b0208bc132aa8210c04b3b3749b3e18e1043247f34f5345143687085de6be3855fee3f57d3ff513ce23c71d2a3899b298cafb94598c97842c8b1faadf7ed61adfbbaa4577a946392a22c0ff3cb996a5b44eb1fd0b19b45bfce324a3abef53318b7b21f9e8ae564abb3019d2c161132450cd3227d31c78c36a3dbc01d9b97e9dac60c03f21066e9e8a1d4049add692584efb394b7ed23d3338bcf6ce90e4d614337744086930f897380b0296ac58833f4626651e8a5033b4f41b857d25e07f22153e90f6d03044584506abd763a0f54e053cec4b282ccd77b0e4912e4ba6aa6d0b8ba6458cd56024f7074bdd5e6b18532311f08c3dd81d482ee3d5bd269db8b9c8cb4134fc5ef7ac9519276bf0bf3ad7cefb8d1b1e206af5fee249f299bb70989cb50be8c149f18adc0df9bd8457efc268115d4eb01c46f7c7728a94b6406fbf850057222940eaf2fa22fd608966568e80cabf0c7c3274778e47a14c913b529f2ce5e41296942796cd221a94b824646c499d1916ad60e6b2c8cb06e0c6f02c593cb79344ad4c0f183f2bd17d5f4a59548c5d1e6497b2bf9c195248944d1a062159a4804c0828ffe24702e0300a14648c08fc78acb4610d7ea21ca0a8a877960ce2875238ac8f122da404d301c6194fe1bf1cfbb76bd5d84d049a6b6b8380d32cbd3fd6a93b3ab6e31e025ea99e6d366f7eab33e3bd3365bd07df2fdc7accd091ceaa43ca8005942bb92969b0501030587954a6f94719ff4c53cb87cd342424cacfbcd2c284cc652ec315984ac8684998283bd511340f76097e078a74cb26adacb197b2c7df6b8f71a50ff0366b16dcd1a995d3bd680d3dfff9eeaf2901f445b7d39c72cc502c4a17172eae7b16fbc7db17747f5a169cc67969261116b20cec1a21f9bbb5a381d0bc2619803fade69ba794caf697a24ba3a084536d378ae87ec8b7dd87a503028ef6c326a543ff92dad061b8acf90585b29007c3af670dff693d372ee4ee164afa72ab277c2b7c772a0b0c1fc3e0416846a8e3b43a6251d65f38b121a2da40bb773e5825b094e1080bd2732a64f67f01927abc8fb023c796f9aef4bbe76e1a2b1bf7c029882febac380e575de30c0321f451015d2e0109d8a8f9d69ee2b273e0bfc5581211b98ac45dc68f2537f206e9cffcd9bccc8d80e521c20f5ca40992237cd52407e2ce52223e2c089f41fa88b205664e811c1a65502c157a54b98e6642d472220f0e3dd61fb5323acbe5dcb718349daabeb0374c4ab79a93bd62f129d9a7f312140f3db2574888a92b2a7e249b6443e85b8e9529790dc9f95608b357b9aead2b1d855f3bd0f80a1f2bd248cbb85865b79bc61e66179ccb345b580ef58f9a3a760b67a3485360224b3d751c322cb56abf23754313e72110d45bf3639825f9d7bb2b1923960719645aebd84f78359c06ae775dbe1a25554aa421da21690af3cf1a2951448749cbb6d29dab6b92bf2d210ab5f5c32d822ca18f306eb069a8499649026130d680090d629337716429962f4b6eac00d442d246be012fd7e37b9d5f0626466b7ecbb1f0d85eb3864e455f6bfa4997837223103547f357399a630531f313f3240cc6d0e6b8957e8b5d69e3e1afdcb00acdf9bfa44c0d95aa8486cf124b06b845b55663e7b746b967b268fe9aaa9013a40224cddbd437ff0b28e87f18421d3b9cd997000b5c1b3c8b3c07ad4cc51fc491c740f87f0612ec72921266200a2ce15ab03a1689ada9e38bd4af596ac0cfeb07e01f2521943c8a50010801d0fc2dbe6cdbc8f4de88a4d641e5e6a4054bdf369c6f4aac9c9c8634dd42045ac6c9026245f2b6211ebff566030cdbacc8a9151b4365c3f3d91771fc1cab73bdee61033aa539963bd1eca0d7b486ad1aae7dcc1a392e1a6d7db4ea0009402c8f5d7a1964bb1a83eec61f1c7244b3f3d2cd5afbaf399353f50c8e40e0d17a318a8bea1f0c4e79a6eeb53c92891488bc03e497b65831ae91a19005a8b8f8227500091215ed52e70cc1aa437cd82d3fecd2ad70bc347f4a568aa0fe554042bc9d47ebd4118a9be9290598a834ea2ed2daafa454db5dbaf116b5170592ee3bd1b46266770d4ecd15581ed4fceb62ad1b6f31f449db9b5e84e6a6b4026f6624f41345ae480f2e10b0e0e8ed6733445ac0c95c15b47696e18bb98b565d8504c5f5c9bb622f09ea37cdc758effadffb92b67e60b0afcfd43b62d973e14118e33b155ad669ef0bc9051e5600c0d2a84b23adc3ba853b0782295a3fa26c8050330bbc3a572e2202cdea01102f516564eeb5623343160f618982961c575f5311d6dd944159f70b30414ce37af4bb47af31ecd55f5f9f438529fb85aabf086f81773cc11a297eda078cdf01f8e465b7db2f43ca511598138ea42dd29529cb2540e393e108c9c7d22342834557be4349f59ec0eb22e9c41b524dee8f80668d2d99bad886f7ef4a841ae383810c231158a1186cb820e96e9b3e238886c347a0ca9078034370342b112b3121064cec0dd115f748f7bdd7be79c8ac93d19ed14061927bb6fd14ecb2851343e9fad4d8deee07b1b45fbfeab20ec37950b5a684398a8870c61e3adea38d2e5eb4147e5dee9cb6c4a7a89991f7bcd0386b398dca56a3bf8197c7a4a8d22b1441d68fe280ad37e614d45bf5674dc2cde26180d1d064b854724c92532c065a07126b8ff084978b0a878ce40552c2797bcda00b728c74bb3fd8d8637266806216dba4fc94cd3829d05b25cd3f53897b3df62037a6ad6197c3e574bced9421ea1e499047d8270be2a4d17b31a054180724adf1a32b247b5fe8651d75e35edca30e57c6004eb2b5041c38acd34cd374b8e463ba48b97410f0241ca9253ee6ea8d29e0eedc285a0f02b8c7cb1dd62690bdfdd2669d3ea66a205fb5af1209cc542e2d0fd455feacc7d469102bb6204d1007c22fbd2dfdcfc2da5c2eff159fc79c342ca7694709ea4b1a72e320068a09319740dd1c1fe101eb4bfc744405c14cd9ea040cbd0b032af7f4940ea54c7b4e4ffa217928d281e951cd4c918be9778f685e0f8981ec58444cf6046cc7282cba2f6e1ccf0a35204d15e98cd5a5e36e5a20a826cc9ddc82e1971b55a5afbd0b186ecc156eb9c7b53654543dd081f8ce04c8012aeedaeee9220a1532041c28c63dfdf118b3762b4e506ff046335f5af87831be25eb3e9cff93597b7ba31a0035a69882635076ae9e72d56e67fdf6604223cff50a0df54aa08c3e1702fecc7910f27d8dabe86225e9601a0f4977f7b287270f090e41b023ed2383a9cb1e11b9b77da6f0cbe6f6c47a0d19ef311aea2d1843f7d22e374eab5e32cad1499f66162b1f5d386be05cada415a74a9b259a45fad940490843044b1e53eff11e4c7b59a0d817aec0f2068e8e4570d2731c4a2e0b7e1fe50f3c4965d7d9a8e9325d3e57247d56dbb9de92c3042d9996b68c5520f1d6927320464ee7350472a325e188ee96e48ab306add1b0060d4aa16093461160a01bdb265c5bea1bbf59028f3ea0f87b7bb03732ddb3cd405d305153decac49a390bfd0bcc40de0765136f65cc1c007dedf308a8f30fd3e1e01155184026904c9f4ecf03193af1d7f197219b2dcd0a31eb02bc3a498c913157be05eb238d6241422e692135300ed974835179d8c114af12be32df6795dff0e160bde9a5855d3887c3310c5d2ca5a5b80ecc1db01e70685b2e33614ad38c65597487130860c3e1f918cc1fdd59ddffeb5882b17341c3d6e5010943857fcf27eb9177d1d01f4eac89643c29832809590a087942ce309b72ec9743d9b2ead95830632999d0b23d5076b9c414827ae29092fdcd1a3334443e7eb4946f916c01f935ed2ad90c9791f24f212c220150245261692c3c674a1e9f06a8f19c0cd8fe8468834281f613085ec99b381a74bffb6ca2cd8c7b1e70411110713313f1d001cd78f878aef0f570dfd1ce8c165d3f2088c1a742e0018cc83b6b37cf9c2eb9af4563c051cae7fb9f5d9aedb516c2defd636395808025ef29c2d3e0de265b8c6faec88cbe1e1d322c7cf4d2f901f793d46762bd2a233e91ce0e7f775e765c68e8d5d3f840dda369c945c01c0d1e9ec1f4c9a2830b319aceb05b2739018df45e41a08164e69bbb37c1e9b22d6e0511941f889afdcb02d986c02f9ed82d8ccb94b3cc9bee7f5079508d65432d151cc7b4c40e3ac3928bc5e1d53703b56d9caaaedbb983ef5858050ed237347c3a0536805c06ae838aee568ab7882a5c373d8634803f950d9ccf481a4ba060d3ce2347b90cccde3b767bcaa8e3b06b314cb39c69c3504c95bfd16300275e1b5b3027f896349ff4b251814b462171fa7792d203235cc1ee5719320995c3d88068dd0b8eebed21533b032f57426ba12a65db9e2326594c76ed3470d0973f432669e4251edc549d8eefa2db3a94b79e868177ed4876e24adc09b41aeed80635bc0d101b75a12e64fb119c6514ecdef26961f07e210e1a72ccc86c8e5fd3e22f15127a28dda0078ec59ef3aad33bf8c5799c0de2b6c8873d6ff719ddc1c74ac99580052ae0832b566b6ea165a1d27c369d5a555ae8788011b36c8595e287545e9ede4201ed52c1f7dd087bc79b0f35b267b3fe5215167e0dcad1bb8fcbec9ac4726ff2023f9f12592a9817372d647d280e71e90a7d7c39f880e5bf8896c990bc8c4c291828d200153ef1ab2e400d5bf3ba3f60efd724ef6ea66c2c75390eafb1b77591017a187aa7128e77e15b9839c9115685130eb47eabb280212f9e8389b4e5d8061a6295ae85ee72c05994836f800abc11b1175e7e3ca65179920b4446192bbb170518689a2eeac670ee167d446b3819f29b16dcdf5503b0b42fb8dd28d3b3883f13a4bf36b2c9504518e63ac1cfad70396ff85e3b67fbff887578d81828fe5f111d7b85893435975b5674863b8a3f9a76d1cddc184eeee39db7853ac420f095170fde115a7b1b3a7f383ef87113a6f77a1138edec7feee548490499697cf599ef2335e6f9b7fa4938679371ed07813e058b91201a4848222fcc5e3fa2d797501a25a866fe0fdf394232c5a494beb9e63297d00195efb37074430e9a4981204cc61eef085265e8b8de1d6cd870769008211e165006e8b3ee5423bdc44e5198ff531c011a4d3bd57fa161a92ccfbe0d5597a2aafcaeaf6cc042b5cb79d47e4590012802357c661e7a87a56844ce37eac8a5871cb85e2f34cbca0acfa14f77566b9b0fd9a48d11b07e199d9d244cfecec430ced755a4ac507affbe74b4ef2ef252861219813dc856b9280a97a478755925040ac19e359f1512232e2a1a348dc4ab5b21d0953cee4b7841b5e6fdb787ba135d101ebac20752ccdb0bee7b8b8b59f4492cd7062b7535d5139c66c6380a230ebf3f61b18aa92d61ace15b82be68c445fa2b3a94148c49eba2a8d2438db2b33b0eb48f0f7831b3632297f29fc8413d0fd904a20d7ba25398186d33a0eeac9278c4d31547d3a8872e3bbfeead80350f62b30116d16f6518251aa9aae6ebad711e28f87cc9d3d0bc79e5abba9a95ed1281382933b1755c135eb4115630d3e4dd4e0b7ca034e98479edd3c50d57433b7bb0be00dd1de6d8e5f68454376add37ef224ca0aa7cfb5ed03018f297fd999eee543d21cece1629756ea5e93104701762cdc0a55b99cc72c54a23127914960a654dfa1fe4ee6692b34adb983da58f330e7e0c86ec396c3116a6e9caf0aa6b9d47737d05b91d24208aebcf80cfa68b31a98a009e61a68452ee12b07498ca5b18caaa5515f506896619cf48551316a095ae30a84e48abc0bedc74d6825aa238ceace417152211741dc14b488c6f11b0298d1e8abe2f27c2e135c927146ecdf7ac56ad420e36ec47a8279d5cabf88a0a360d43bfdfa43b9e891f5120955f2d4bdc121606227b6c15f345f9a55b233198162bda3808f27eff2ccbd4ec10a29d713465fc980792f71dfac2c03bdeb9988d1584fa91df81eecf435dac93f6ed2deb4cd9179f076f65880a7e2583a6246134e87b59fa14fb6d082f1b06b890b3ab334c87663126736ddcbe0ed487e975a29e2a5b4e80cf24a821f4853513b383113ea252e5341676f53cc7376901f1aaf24817b2c48267358897fbdc836fd4b02fe9e1161daf0850436efa21849fe994db36ff91a3ce2a677eed3ee2117094ed02bf47e3c88406cb6ddd4a4c69df5a5667fa9c2bdc3a6181ccedabd0420debdd15f1b163f15724845bab70224e26375714010772b3c3000ae68098c125ca95dd22805762a1d501748ba4623c878c2536d2eeca896267212a605808ce75b93526220c2c18c2fd0425ecfc409eda6e0dacc8de3eb8024d9a20b29a6fa6b729f72ead4a9f24c08812311ab4d54cb22663a5a82441ca9b84c95af6e6f0f00bce270fda7e439b4f3d15b556c175f8fdf289fe72668fffc1804643e599cab4caf6bbe7d660a2a1324f1ba66f87bfd12d5806cf9bbd3034648f277cac80e3dad0d4d5d065f6e5fc4945068922e07ca60e5b244625238eeed4719bbdcd8d868d756bc12a956e0efbeec00c1ab342d27f1d270498b2103ecae4de962435aaf88ac04186f4c8a3e2e71c2c09fa18c56627bc235b09d1fc39e214a784927feaf510c3c0414168f4cac9d6301e80d0b79b97fc8d550bbdc44ebf5846fcc340e67383c9d53b2a1b94586154a7267c1907bfe9ee68573ce8d99a711c9da911d795fbf0f087e362c461a4074a3a1cec33703aea1b12f87aad29cd97b8c0ee78cf8d09b2a1fc1352c497ce72aeea185431e962667e6a48126e294a1fa8028a0a135bd57068ebafcfbd589cfe535507faf50b320619186800fb993ea325d3d004d6b68be39fce6d70ab560a8efdab21c6195aa6cedf4ee61634f96862b7f7992e9df0fa250e0f25b671288bed15151d773286b3543c0047007a615096bf54ccb45c7da10eb3291c28ab2cfdf79e6027b2a9261c095c78470edb892fa58979c9880797acb8f09fd99a8cd441cc119d12d7cfd06d96edaada9aaa5f4af9e3bb5421b83f6664683c38fd04800d6152c317a0e3ed68287a4e6c0389ad3ee54434e948af4fb796b6d213911296cdab398c1e5ef689841cb2e4aa63679052def2edd541a376109970b874031e99609fa8f000a06778dbebf666f4e6f8e41ab20543083d5f506b7f88ef308bdee04766011f0cd392c11bc5fdf32fc7a14fa91c13bf3aa3b9be84d50f12d6203ba8408c630a1e06c80b74ed54aca8519851dfe341de87ff0ec0ce0b72dbcdcd19a5b84bcc9b041b2e04ec955f754ea52431acfdf375bdd7140f4ca9a0619458e0d197b9d572184832627fcff4170c1d05895ca491a09144c5209c6b0137a03579fe74b02b670f2b282ea5c15aac900a53cb60309f1540d09b393da213a2c6f949992404a50017cc3f11c854a7d4b9598e3bb233355c0f2a782c32b5f1b2954c206d44cec24e2fea355dc6b919550164a6814945664f397813afc2ee4939962ccf83edf950890f245df5fc5a4a027a2dc4e60031b93717114f900931fc88c43c6db6872ebfec1cac247b216f38de3af3895fcdef00eb6d9f00c32de74bc661e0b5b123448ef61a0b026dc0946b3abf48ef6ad7c763aae1e0162a13fc605b324ed9489b5957e806472b9adf3eeb35b76e109ef09902b907f8d314bb8ae5b00f35b7b3bd99320c163f1d0f7a9f1efa43b36d29045ebf4d1308cddc170acdf6257d668f89665ca10ca55653f44c2613af78e20132c2f8e2c7457560d670804077fc3b8b0ef8cad8188c0c24e2aac1b9824295e7f6578738378c55d654194282d186e7ad295bbc5d1f55473be32fe31a919fa6729dbd35c77aa45b1d79fe65a94b67bab20d47bab129de75ca256848e7f6a6cd9747d606027a2c15c7c82996cbaa34275bd40b9b9d244be024ba6672e1e7dd1dba510352a9445825ae47bdbaf81596048dc3a7325d22119dc8ff3f458e8c1b0a8048847417c41a7f6f4666a21286b4df234229225a180ae1467cc29b5bf788164e5c60dc9144bb4d7a03d9f077e15476698c7292eb25c42282e9fe3a164095d306c4d50583d0836c151d2e2ac76d704124b589e86128ac118f9fc484d30f6831d630663236b3ee425f34363d4138276c6b77e672cb2316d2abfe95a181ceee595ed6097f593d17f5f51fbff779e243b60cf18d08fa2588b099fe34c9916fa0dd0d1118f4512e362a92ed4459b40ac521c66987e8520d3e773435c7211b74168b52794532a63a88e72aa6b0f0d4c426edda82088bd80d61e06c87ee0577c1633d6a061e1dd3cda18ac626bf7912d994a48ccf30d1be25d3ddf685ba8df7ab532aade5a0b89f4188b835fe8627416d99c13fbd7312752061e846f342a0e53aff64ea450f72494e953f74c31ca50599a9d32e52ff6fba1bddbb5989abc7e68af1bae43168875468b0432799fe1adac2b610728d61ca900456a5cf5646bf8438251b7017636f3bea7f8627ef919775ed74205f1e93f11e1d347ee26dd72e31e5f24f8cca5f2cd905ea1bfcaade0ef1b23d0555e2b128e92c570745225a2f80506157bf8ddcf0febe3b2d3b87284803dd3762970f500a85062d89b8d679171c92258012498996642d9f32fc9b8914223ddf76b9228c6c852c41f9c81f6e1b8aed64a680437d2e8fc812468bd490c07d7d23ed50c0de821816380697a0f0c4600414df4a2cbed15eb6beccae630e87326898b8438ac274330a7009ed8ff4eeba6d0ec8c7f10a6c5958603769c2d49c3f451bcd83bec98172182bd68e46f70c6c146b3df9792afcf807b065d1df44b1d3f9a16cc3ed7c56300332a404de00cc561e8abdb366b02bb97d89e1783b88720eae99e715f6efb0dd1f16870ba292b53acca4709233394d4e830017a4925897bf1a7f3c2228723b6b0aa4784cdba6fab4402c28aeacad2b1ad7ea07fe04dbf84ec0350d4c0a38a5f22dd89059b1d89dc4854fbb17bb68850ec92224f2df873c113aab633d6229df860d9dcb5759cce6458d0d0d068d65f11061e7a66c552347b1c0475d3adf0a117a15c349f90ba7e0ec0ddd861864e843243d00205d6f7f784e63cefddf6d2b5dda21e60167e934049f40c3c334327300ae1fee1db8dcf91e861a288d5b8391d68d25ff8fceabc18168a51d1bcf6162cdd075f980301931a732067db196ede699e31593c56a31ca830f78c08d85f7d0598cf18df04d1a83744be91d62a9d48938360dddca24726e1709b34fa3089cce740aedc2468af8bcaee7e8e08d4a1fe2ff7912bbb10342e4f1e0449a95ef72f96f0e2cc86646b40d0b551593f3f3990a56812270d6bccb9c5122672ed5f45f1116756edc25b1053a29d63b0cf75220e817e50b1b594eb5ecdc079a8efb169fcc39bb820652a7921b1bb5cc9c4822a4a06aeb22c90eccf3c5d3db80fbb6d3e655e309c4f49e6c56edcc158feb0ecc59371f7d1fadd6dc96f1bd1bbea4fb37da9209fd80d90460baf6539345ce2f3c6c1f5c812074a5f478b326415d3f00d85e648be949a7ed61821b81aef07035a8e614d30c0a95c778b392a6c9117bd600c921f2b6b584595ee597384de21cadac502041981537a1874c7e2892e52bb994e8c3f4e7daabae54a530de5402587dd95a740df90c5ffceff04a2316ec2e79178ab83c9e36da6009e8822e048a0cb4e3ecf78a3d235ef3d535547f3823e356568660deff8e6b42ac6d603904f28afb5d089863b405e9f4140639e2371bf0b03d30c41928a0f4d2899efb2079fa7276473d48b26611221288b65b272f62a9594276fdbdfb7c3a75f4280b93afc08c79bea215702d1dbc1bdc87111e706f693fb3d720a0f002731f7fbe7336393b8816aeaddcd9781febf673d810faf0ec607e25e578ce30710747cecec39c45317a4cdd837e436610bdaca35664fe436bc093db244077fe02b795efd71e140ecc03667852eb3af62f1228a2ceb412f361e3d17623d587eae378b63b5f67a2d6dd0f63ff41fb3a0922e3f22c547f8e936f3ba7a067d15d43f8ffbb69a613c78ba56f51d9345c54fb15228ef14f959b31bfe59542d1d96787d1b10692ee09c48208ccaaa8ccb67df32d091bcc75cfb8f30ed28bee0d15c0f952c97354709ae4ab77dd9fa2ebb897df2ee1541b7328936f0644a69dec6593585b86c3702abf0cb12d740361b0d7d7232b730943361923d9c3f47bd914be5e4d06202656a3521b75c1bc358394e95d4b283da8b0a31a6a8acf838969ddb6a54dfbc585bc8871a31cea3c2d0772c74984283dae9918293e52ac715eb27d8ac775a79fbd4b0b0f81a3c66c44b92c05c3812cc12592cdbcf2fcd8ba7621200be3113f36ed110e93683de0c4c0b88c66efa61bef685fb8c17c46ff000c53232380be681a24affa72d07ef36e0ae5c0dd3ea616ec94567324fabe7332389502a67299e45c203908eda045ee73b927eef6129e17edceb74440d44896e348602d32c40312a7cc8fea01c0bb61bc870ea40263ea125d48adbd62e87b1d254ea192e3281a08567aaf8219350686824d19e74796742a05c1b82a755458b9345fc7ff8fd009630e1d46267874bf79a88eaedbdaa5e61e435868e8aac3e2b4370a8f54ea37a111c325f4a07dc39ac01746a3f98e194f0cf38a4652916baab0771f2127e9ec7791b0e37b765985c5f0d073e42154851f1719789e2f4de1bf9b8c3d81849148b1df87eeedc3d6583cd994c43071e6eb1c0150e3ca9f5b8a5f962ea613077421a8f906d4aaa5dcc35c78ef6d8ce46ad33f", + "proof_hex": "0x00000000000000000000000000000000000000000000000469753df342aec0e0000000000000000000000000000000000000000000000006e4d829d66aff749d000000000000000000000000000000000000000000000005f6499be2b18300b20000000000000000000000000000000000000000000000000002be6db4c5558c00000000000000000000000000000000000000000000000eedb4b6056c881e3400000000000000000000000000000000000000000000000867b55169f2600f58000000000000000000000000000000000000000000000001bc9f519f74446bfa0000000000000000000000000000000000000000000000000002b6d6df53885c000000000000000000000000000000000000000000000007269f9ee62308a02500000000000000000000000000000000000000000000000fc8ef0ceed9608e82000000000000000000000000000000000000000000000002d32a3b72f08734b600000000000000000000000000000000000000000000000000018a5af26897d800000000000000000000000000000000000000000000000665ee11e35db35bab00000000000000000000000000000000000000000000000c29f716629ef9a6b300000000000000000000000000000000000000000000000ef868c0047d6dd22700000000000000000000000000000000000000000000000000026ab8350fbcd619e3c65ffa1c0d29b2cd62700cf8d71ebcb032227e21f28af6c3d9993353159827a80a592b60afb7bd0a5547279d7b7b6d745bd21e61cb30dd2fe6fa64ed7ee81bddec82e6608821134bc64e48afc548d54643761d84f4518e91e1bb576a9b3a1efdee0270f6a11edde9c2fd71e9de5a134a7ffcfa996506f17b7ded320b946905e9267cb38c0568773f0534e90cb7b63d7211d220cf75c33fef50d1b5a5100e055a47bec0d9798656da3a784b526caa90e53303c14eb63b919c2949535645bf0d9547c8dce32e13dd504bc6be4948f9635a4189cac34427ead69640255ad33c0d14a348d9edcbdb6ef4d4b0a379e7fdeb9801b76a0da963bdb56d89ba8f3a0210b7c42426c99152b8bbcdf2b36f1c1855f0ceb7482c347de29259ad7e05498a03d6dc7925daaca12e8661b8410ba878a1497660cac39150a0d2d1ca7b556cd5217867ffbd422a5ec0f3eda032d0da1dae248fdb76aa76f2aef8583db964d1491f5aff0a8af8585259f308839565b5bfa984c574d4cf02f2552749a67f4ee7f91fd21add31916d3b40f4006b7a83ebf00c14999182cacfc3b853fa33eb52c4bc0d7a9f47486d5c9f5dc5f1fba6a4c5edebfa27f2b9d47ef6a7de0f966356dfac080b3dab741554edf23aad2a27840334a132e4ccc09bc438f503346aad442b0214216a2005c8c7a405b68cdc0032c8a6f8ff1c663bfcfd165d7de791193c31c30dd9f2f2f2a0431be2e4e4f1fe5b4be54f4df8b761ca81b8634e42a243789b7219142015b3808efb3a739c019f139df3488006f7e463f6d19fcf228bce9fa6d613cc0c01c36911240ee0501a0cc007655ea1fd15b8a1ad2f8d1ddf49931bc0bf177827b2cceb2956abbee92ecef40924cb1e618efef90f0194b8d8df4745ac94211fbc877e3f1c1843dd9c04c81659fd1071b38a33797f6a6c395143aec09c8901b9d02917af3362e348cfb2e9aabd53ebbe6b3565508163ea1901f214764dda2cc1ea3a3e121b0655786495091b1b6eb05be9d77b5149795f94e4bec6e2b183149dc7fb2a6c49197a09199db3d00a13ed9d3fe11a18f5fac973b7349533df4922301951689c04b3f866c7f8425c047237cf8d409e8ba27c49e924268817c9e9055066deefa06a0b869217f5fed30835f92bd9662aca74e8b06d29e525ade59a1fb24ae716ec7d331fe77e298f28024bb1fdcc10c4390920b5592dc36749909d0c0f625429773d2393a4f713600cabfca65ec0617333ae5764f69790a9f97bab2f003fff339c5965274e74d713ade8d48df30bf48503c109d9e6c124b70b6277299d62ad7b2b7138796b217dbcc3c4acf6017e1bd6fdbc366957610a0f79eb4f17ed4c180fa64e56f7ce6c9c3aab320f1552db2274fcd7a4576de6cfb0d3db3c1ea4b1ce1f3afd3ab96c2e78be599e3d94f43d7f89851fc6ed825d6658f005e815a7cd1bd26641e038a56293b8095be2f287d24612af3ed6ba44a1f3f3a911e3302a5476eff60236e0580cf8b25f9efc8244b30ed8786f66e39dd4456aa4f024029eba613ba4fb9a7994e9ce5afb6923109490c62e0c988df549f2e9dcc3a56829bb3f7054a4b8cab4aa1769fa658620e87d592cbc03f9a71bca647f275288ab02dab6867241f0d9d7a67a4b33933a1709d75274bf5bbdca414d3ec79ed120fb064ea0f18c25252dd3a82b941e656196dae6336b385dbc60cb74e8cd668c6f631fa549c5ccb417790c6e015e9adb9d640012eb6c177e18eb7a319e4fd7a266671c31bccb4604b5acb7226d74e075d4276b4e9410a595e91dc5f864d35c6e95b72d4308c3be58dc29da40e25d1f63a36940f572b901c39f31e355b075dfc95a2d2092ece23729f1bf832fac0ec1ccd994f016562ca1efebf54428b688f1603df1076714c5d7d7ccd14a87225c15c5178ecb331bf323ab74f8240715fd0166c33605affcaa1b4b75d30f034659860df6af13b6ee9e6e5c1cbc5e131c2709ea226c11cf137940d661f8f254ebfe274cbd889768cc23d728cd2c5082012f427228cd21cf49509a55121e5756aa33e207a548d5a8f15e9f4869564fb2fcef1c4577e81f237f271365e73cbe12dfdee90ca49799cfef0cc0af26d57ac820007cf3cfc9073dcb3915ed77c7e50f58441879c2c5bb450ada48fb95182dd02943e980031a257c5bb6c116e0e17a1efd1877dcc3a988d9b5680f05f5dd7927bbd0336c143c0aa03fbd503e48787f9296c4cdb00160adecdd0ac45174988fbc535e86d6e4250b3b669d61dbca0afec215f54337b74b36820a3794c4824c9c812aecbdb860be238bcc0ab026c45a1329e6ccbb1f0e6abd83cb9910e5468c9e22ce6c4c3c5d1b2892318212462091cc6f082e3946445e67456576206a0777bdafae6420bc108d0d545b60b47a8647c9acec31abd3eb4a940ce24304658f9ce2ff50a5f5a656f80dcec5d9ed6e857d317c33e96e97e19dea73112a08b301cee1c5a26264b2033918a03534a00b9812d0dd992842efea7d0323402034bef78dbc11232402264318246fac64ff0d90acbd0b1930b4377ba08f35e91ebf526c3802640b74f6b786ec118f486e979a8f8d9bcc19307bee149a5a4d459a145723fa863d8230753eb1dd08f4187ced1f037867e3308affbc4fd535746aa6760d018f75bca7bf3396a59902320058d6cd5935e44ea6943d47fb9d45ccdbf8ef6de9a5231e2e4e2a1558662b10e223298ce2cc72aa45a021f1437be501b2743c08bfbc9708db8b2cd7a9ce17256be9fee29f8d3dbeffea7001aa6648ed7fdd53c0e9117d88379f75466d7c2cac187ce9ea645f137c8531c417fa019100cbdf78be2763d38414b97a6b00871a954bdc2d8e1df7970a636eb0e9d8e5acaaf827e955adfe4a8a2a43598a4cba094833c3e3dbd1f261a5d75b5fd313a5f240ff30d989823dc45a3c3ec90082c626ae27a87be9dadb61eff083583ee3568378e95a1ba75f4bfda023c820466f822adc5410bfa974d63142c051bcafb9f1b00ea44385db8cf1d0c36be3e71899c00cc356ea4a7f52ace0bf72913493c437e3a0cda118619333e1b503b29a7e008a0159746030e90700e49f97c957078dfe35497ae3c4fab77cc9c6f080f84637291d9bd340a31415e39c83c58e3f3b901ccf2e2e2356feb40dc496008982bd189118de77f08ce5a1515447c4a04a8c35e9c89f86d164f10d3df3c3701d8148e5681c027f18f613d5f5d6b22de99a7e7c5d1154db617adb0f4aa4b140a4cc4946ba2c6a68f07b9c6b738d4039291b0e7bce61dd330aed09aadba81f6658e15c46251c44e7e03576d9a2d902f93d2cc226b10a6e44adb7ac928f8275333365101c821d0ce2c8b77aebdb5aabffa4c641b602cfb62c3c98c9f966b2d950a193a4c6e4196464c9eab169d15ac12cf5c4ba880c3bb829afc21ada4364d6a4f81299de8b21679e06e1e557e7c831c03cdb1b8629cb925d4fdc7d44fce7f4ec1517897ec72a2ea327bc07437e1a70ce03392e1d739c2f913698ee590e86c3a7c5e01e70292b73f7dd483bd896583d2bd30e736926227cf981f05cd4d718c6f8025127da4b205d377c16c2d412e76aa1486b04538dee538376fe1522413e41df227cdd52e72c8c867f4a3ea87ee1328f964365e79338fccb36c83a0518445e3c09aa2005ef15405379466c46a41cabae490c736d70476264f3b78287804bca97b68bef27c409883a5ce11bb36fe046d33a2447f7cfc35506203a2e3a01d389c060aa3604cc237fbc043276f8bcbfb7d2d1adadfaba9cbb70a9220efebd6ffc62ed96bd9bf02387189dc44aa75b967986a74ece75106f97c17256baec95737d6de103c6d7a2118ed1f68bbf4fcb6647e625e0a210b31dd9399f49665aa4c27d88a639767a521dafb03ac0ee4f48394d53fe6d209740009a1c11886f6c721cf91e29e268e8cb2a7dba0ab3bcfaf639f230f5cc32a443d1f9afca79a77113657e12b3a4023f130838602c3c9bcda88afbf7ce8fddd16060ec4e0e955bffe48ce7795a750121a7304f58bf35b291bff1e28314c5e1aec8a7301a178b3e2e76b81f27951a2550b817406d894712963faeeed76b7069a0c164e685255aa0ec245c5d223b36b05f760307a8d077c47184df6356e68a3df1b6e645a7a1f68c3a4ec30a79497dbeee8821f4cc5aaee04d9c0c28cbe66e5cbcc48994a4efa36572343f005e385aaa301e157faaaf53694d880169b06e0699f6aa01cd14868786ca9be54a5571ea0791df156e53a49573829a7493415d75ea54104d64b800d4688fe718eb4069b59f93162277d97ac74c5836b5078e713d2181bba46a58bd1be7cfb2d359473be276081f1b6ccb434bbb6f226e9188bc9bcc75826becfb2b589244ff57e97a2994682a3e007aad5202beb5bc1a5ee1fd908cf63b2d36f76e04978c164ce4d36a3646d7581474432c9e22f05b48726087539ee97f746f73cd9d414d242ab5bdfd7609d0b32155a9da08e2067a889517aaf8cb024a8168f94dafce6f93b2f12dfc00641d5218c35fd80cc79d0b4bbb1f766f20ad4ecfc79ca94562895c78057587e9edcf1211fca08a404520fb20794782ed562767d84c1e6bd5d1121a2b58b63d633cb3d528392519b02c9a33d6200c2b94bfeae8eb83460ba6ad4dff419969ce80ad48540cd03c06c82c17abae5a66cd8db314d6cbcfbed1472a446afe81b08ee8e710121bbc002b678d3e50d223f02e4edb538e65fe35f26fa0d21cd77169d208d1cea6188ad9b99abd82c6f89525f6f1034be005f761a9503d049c955ce43bf0997e192ee5118d2c94ab12ba2df5075f42f1572f28660109c53a4051c8aeefb2015915127447e3992602c10f17fa0248d4a63d3fb51d02d7c87575ddd2a228838d54e015405e3aeeb0eda949ed50111d0881e0d2eface34b66941e9ea7246365202f1d207ad9eaf4c7ea11527fa2ceb4c32496270b04edd79eca3542d97606c3ad946601d47aae61d27411aabf3fb0d5c57301ee1ffb7c01ceb4d04ff39180475d097f2b07fc67bf89790286b97b1d814ee45b760d49ddecf8dc3907cfae048afc82550a7f416d7de4c9a6e3a847c5700b4642b637ff9872096679d2d5921eee91c5e11110a2da4abbceb28aa0f9b4bbc132493a2ec0f2712ab0d2cb8d2c589168f9af2f14df7d9de5d4463ff031988639bc2bc42c844a737ca569dc14045284ac011e02992542a5ae3e06562f08bd9eb6d695652b0c0207c3514b292402a5745a60cb22cbfa325db3d30866e1739fe38aca41517e9076700489344ddf68c38c28ae9619b91304c3e55c8f4ffbb089b13b2f04ce5d61caad3d2cb54341b5d1a930d35511de0fd7e69802c35962bd45cd5733a23093208051359e4257f5c9cf68082b362f3744ac22c015a9ac28540106e7d03ddc305882758a50c372a580e5d70c09a720755d74fa777039850e88a289095bc3fda6e3de76a661307c2e77237916761e1dc2e2fb9e5e3e31b522be2e0d8f2e3e7e9cc1dfecb73a1a79a0e26c7c9083080a1e1842116ee304103ebdccf52062bf9578e864afe05f3983c17b84f7bf4d1209460b438ba34839d978ec1c5bf6aab43d09bcada67751ba23a5d39910102bec0c09b6ed88010416941c845ff0402963a715b14ae1a371e9f1913698b402ca86250046ab1d84ba0a6bb12686cac9ba831fa28fa3d0ba72589da190425b42548e220351f64ece113e51fdad160958af52e544b5d08fde40fe37bb84cb659bf593033e291841fa82a53a8f2c141b596c4ed461f562e632b2ca893c12a53bf0de5d2f084d18fd57562a366766d549e205cb36846670c81b92ceed909400a673e53223e9c3b1001c31f367bc9125089c292d5c65dbe914f59cfb0c1b702c7847f2151732806c02b5aa5e97871f60839b79d3e6feef3a3f696115c06e05b0429e1d5321042be272a689d6010378e100c44a1ea4c1841d88a61ded92b9c04347056b3e098fb4e93729884cf98a415354961cb468d38c8c5dab2466952e1863952de5d22bce831cc9e2f11fc39a4e1911e4e391aef8fd7e2f2868e7e8593519a4dbbafd163660310bbb68814e644e234d2a6214d3c2d84d5e78091ce6a3167f992d6c411b70840ca25c4251db8cb551e4a37170bcc4e0aad6a73ca6eae85ae85437a8c12fdf8773e4d6896da6b5510c65e8e5ebe2214ce0aeee893aac3b5169ace00fd20cd9084610949486651f579981d04ce71f246593a621b94b11bf2d4a53a9b7272a75ec707e5d6e9b94cba7277335b4dbe3a721bcc5d8d33f2d6521047d8b2e33035d2aa05920b16961a8e9f5091d1e8dcb0ef43ed663dd29d95e24307a3cbb14248a1fde5949b811c8cb64d561a5814c4e42db4c2a82ed3f85428951892885a92727050ec02883b4fae76a8ff11f88b279cafc825d492c8d88e6a21b8069bdbe3020b22284e21dbc649e9fea5576619b0d5a6c20662adc00a8cae9dc666fe84d2a33893fe7fd23a4b3602b1872968e09b248a1e5f009b8221019113733a639e314bce17972dd81107ac90a257fb403b80809e8a41f298cfeb0be9d87341e9e8026b58446c8f6efe18ba6b664917d764b67f883a1573207364f3a05ea5ac4124a247da1fbf361caf35db0991d02d7cbeec4e6867b454e1c728cd64859a18ff1d72ade435bb8dbed3cf274c0830a6adc7e9aa296f01e451882b007fd972875c54a2a76150e904347222648306798c03ad2eabf742dee661f1ff2ee8b7aad5061f408e8c42347c0400fa8fd99c1e5d560ffd9c45e274bba4f8e3de5f6899a9eafbc05c680f29f0e759926432803bd257f347279ad57e0cfae3ac1820766f2bfa89a2a054c1318608489a6149c8ce98f751f4f90897fa87921b04885242913fd053c29d2250a857eadfa84a16b5b4ded1c2f89d817a2e005da0b94a425b9890920c829d60b0fc66656f0a79faa3e5496317705e56c49f69b3732213b652469ede8b62007b1e8209e5e0eb0842a86321e49413e7d1c48539b8c8689d932b368452d8f00a415eadc12aeec854463da5ec3e848343d7e035b69fc369e03b45d426c80cc21af387870e76a693d616c271e15dbaf75d32b19d1e6ccbc63ac71e155d002ad2992a221a39a21245e9ce4d06a5d450398bf7fdad0fcfc4edc1f12c3a109d98d1b24c341201ab7ad61528931ed868d4ae748b0935ab27304779ac23257a0b4e40fcd390fe49200b9b9a086a7756db0a14b232ad01be5356c40d31c1aea918a7206b55b1f8d4af81e1cedb29c4368641a2a5d2440c70d6908fde350ac8a26c7f22d3b2f21b2c3632af0f2e9f3c9e52e99d9afb03fddd83f09cb28d206f67086000dad45940c134287e81c13e4bb5bc22ef82e4c5e061e69084a781a21997c063010b394acfd38162430147456b9de74aad70a060df546ca38407bdcbe464b01aa140d5bfd0a61d5158d157b2f9eb42ee971192939f25f02448cb5782b36d5ba5413dde40e8944b03e710c31402a37c420dacb73603c0e62af12c136f833aa3437064f488a6685c8f0b0c291eb33aa33b81a9e4c513e6ac55c7175c3073335d9740cfe4ba38839d89625ce94c63e04178c0c76553844241b8ffbf82c53237a02390282e7cff22065a0568345157ed5e428b107946d5003cc6ac9718b020a21e589158a93d1249c81b6f5edc19b1a461d4886f40991c89be5c89ac77ec5486d77b12852972575eea908a0d0ad066ab7ff71ff02720e41b559dfaf5cc99992a1e82b267146784c9faf18f0a30b1d2c8926de25b4a2b5d4efcf00aee059031129823405e5c2b04465b50e6a6300c519152d3b175595d3ee4a7c103c90a46683bf33900973a27e9d6caefb89a1d148934865286ceceb2eb2a6dcffbf93f40d6b8141f32df15c9b7528bf722ac0cfcd16b5d3b5992965d3f49c62a5516dcafc36be9bd117d498ae3e827c74807a0f6120713c018891bc502fcb2f3a3ef5df92fd36e09123278dd884d45abba015519edebefbbe07b19dfb6eee736e611a001af8182f7d28d2df78f84999ed714f241de56318517b31798f9bedfae1771e43d28c74ec01236fa605728da81f251b890f3ae9375925ce406c5808328b62d0c1f61d507fee0d603e2271f6256b38c56b4d51698152dd71d572f18aef64bb8956cfdbbac8291420757829b48a402faa763299af4f927add42dfe05421d6f381015fd09950cb1d49db81efd5ff650a753c43ef4d6c56742c82663cd9ccde44c04a9d16efb3f226f10221eb3fb7fb9cd29e0ca0a9bef0f9b7ce84f43ea5bf4c7497642e2ee7ea1cfe335df4a4cac533cacec297ac86541cfdbb6baa5d5ac993ea49936cd81b391fd9942ed996e79fa851a07adcefd1c2a8b8f57810e54d04a23aacb01abdaf8d2e2bb8819d1ac0ecd13c2e7af62f8407d63039b06b61192c4d7a82f65bcab66e05e769b154a29cc138b5119a732f22dc15ccdd3beed12318162f437d9da4532508b3af66a3e7a10172a476ec9de4a05d3cef956d6ad5bfbb0ec8923723117f5a046ef296f2b5d88055a90b443c25e5b0b877e3474f28f2cdc79f49c618f44aaa02d3d1638363ea5018f4710ed06eeba5776f89dc9dc4afc3fe942f92f90326771de423f8057cd1463a148594606857c7410f3de1767f89e692f64aeb9c80dbd6063943261cef4c11bf08aa50589f51ac7125d9fd81d005b2ddf1d8b1c5e7f97512b4bc9df1655304994d4c05d0881eab395a5925b935d565194e3db86ea73f9e0cb618907cb0aa0d73720855ad56a543d380344559d846d0c87d2f66c010826d2f0a5280fafcc55461e94a95c98123087fe7c5afd72020c01b5bb159507bac36081c5efff00bc7e17f6289e9d2c2c5e9beb2bf4dc4465c3e954f2393e70ceac216ae4898e4821f8dee3c88d8c1085a01d6abd2a23f0ff1f6b92df037992c73a602cdad1370bd59f65f93ed6344a19ffcfae76acee1f8e2444d8fa27b346719541a4dd20cb3c9f3dc615bac655270d1362c9edad97c23f13b6897d65ef2e3d67b2e948af7af733a7252895958bf669fb507eae810fcadebad364fbb3b5d1a68a1146f82fe31c5e8c26c46d4fd4d134123c591bb36cfce94158faadd437ae2ef3920ee3821c8ef268c38cdcdbb380ec23ad56abf2c5cbc9fcdc291c02269af47df0e6fbd50a5e974c1e50024975c390f43b6da32df921c90f11d18d6577fdc99c120126a58a070d74d076cd1b872e0cbba7354f30dd38057fae7023c6dcd63527a1c00ad87e6e3ba05bda510ec142acd5a3c662373ac3f7a7cc8a10ed678466446176938d996ea81ab6002cc8f4c41e5269d007637a81878e6bf0bd562e0d1b60e10da7445419432b35618cd61bf90079a08b5a0fdab94cf8f36d066351118484606ed4fbf014e02b795dfd62b14b16ba950be77d5c317dd70fb058c0d896e18a1073024ed35b213beac45d0eed9cdc684c954bdf3c18f365dc541b68618b8c06e1d8a83550339c96e752a82d077cfb8ce0211447e4bbdbc3b127712004fb7caea05d2641dd30ce23b7d8b9c5530671324cc9aa1bd271ac6c9be835fec30741fa103c877e6c320cd6c0bab7d62d3bcb698b6605be618784663158b717f37ab03000f60911e4d3e33184fd26170e83152da85d24a8f095334e59b7b62cf4c2ed8400688807ae631070c134aadb8290c356a9521af9333a69da38904671ef89c4d97004d118138a5d8f7d945a78c0abc64881ac3ab0c86060db570be08d3dc2445032afc433cd6ea04a649a3b523471a5d2ad1431f3584f5142b2b5046b5f39bc69d16565ecc4219043483b3906d8e2623ca40a26cbf9f18f51ac5259545a592d5f827e0ffe8b7ff77b8f63b0ef131ffa4c5667134828fe82cdc754d15c7cd33cb6c0077f04d332e7ddf9956d603ec3c9c0a55e1db71f19642c7f876452248a70f3b1cdfb9da087a8ca3055014df3aac51deddcbc64dd8d5a8a221d8e91e749b308113fbabb99460f5785f829d0b922389a673cb6dd7cff8c3d288a77f07823028da1292b1f04a858b4630c8306b8fc5226f918328babcef14b9dc10c1880582877e1d450f991999bb052fa475bef0846a915a9d643aff92ed06420fcba96e673339288c3fc6586c13eb5f581e6e7200163a5e011881ebecf259bf2b84139ede52f60e389ecb2a3b2d75a3cc041b4fca6ef2cb232527ef829a8476563013a4d336e204e8ec63f06e0917808f60401e320069d022f661d3ba23965bc66155ac3623f30b29bfc132f9b01495f4c869c57e8cc42cd2242e72fdca3ae4727c02d9ac881c0a145fa3f17edb13347bbd19819e570e3b016cb952295952683f30761f4f03cc105cb9a489ad41d21c68151afe3def6129200c5de1b932ab352119aeae31df5121e519547cd28f05371a2c65f716c239ab69d20fce2af689bc05f99ce4247cfa29cc49b35b4358a3b42ae5c91d95fb99655002e2b0d6d535f21a6c58b9f82a2119649e434ee728c3248ed73b956bb9667ca6b77443651eb331f0b6520d62c5852e3370acf4ada80391db77ba155e3aba9e8d821c2ce1d31ec09f9898ac21b1112dddc3ef15cb12590a98531763b8d043596632648e08f8b80de1767e74855ad7259558e9228544d393351f17db1a37f55314b6d2a39ff65ff22247ce74073deb24cc708bd37b6ff151588a7c0d107521ae217f13afecd55265888f3263cb2bc924a1faf27e8345e2cab32ebc6aae03b62d115631527b68761882befcaea90c0102a7abe55e1764b18199cefbe32acd68f76650b5a83204dd677195396700b93e268fd11b30f6aeae2288c6b31926a50007a0e85eaaf2f7a6c3c040369df5111e1f8e3e91e40e7095ea9820a37d8ed5408382dea8fa3be255dcd2432ac79c3b2a1072aee7d8c69cfea210a58c99dd9c158744bc20b17e8dba95c49091b70ba4f4038acdad5293ad3f47569799a1203e607107575ad494b4857aa06a2be9d0d4ce2aa07260c845899f56d89fbfb7e18c24130097b1e41bc0ec6d7243558f2191bc1ee0b5ece2d0d55c02d3abb80cfd8d10d6bbf360068dcf6cc17debe3a4e8ffa3287fbddc25ef9071872116ea57fb9055a978d85768f3dc162876957749af16512290c1d094e99bde4c38c864d31bbbf85ce2ee488f943be32e2727633089385f2b461d8ca9e0855827cda5fb219fb1717ff0a838ed1b27d82947288e5e8c14590e039cc9b1ab4a33501362144ea57353d0ce3ae7f845bdaecd9e1304b5472ff61d5f0fe5673507d3b79974ae6d6294e16ef1918a4fa4a8d023e89823124327d21b74fe4ae3c1ad52801ad8210a3cefb6ddc0297038ce08f9e4f49ae8f1f99e5e293e702e81f1c7861c1c445fcb48d92ba77eea9b250ba2967d506925efef7f261ada0b3d9f2742502c26d1ac9f750649cf0155a7e327a3556b2bd9f20e009b9601165f5c53fc4b398b8f3f7413d065aa3fae26a12917fdf716f1360181fd1dc81444a57a6b94fd298742cfadfacd30076bfc6ab47be4f09b66cc76b022a47ca5191e725f35288a70698d51c5cf43b77c2f80b2b3bd4d35c2ea033008cedc2f042eab11def2bcd80ba95c3ee8c4fb917435c62c6aeaf2f4a7131b429b5cb2a4ff23081ade5ac7c55b647aee9aab520bd3869f9c93c36aa7326ca6bff7af3771a201959164e8a0978053f0c13e7a87916c47c7d7ba0d1f1d1c826b8873eb31f7d22a07070f5d5fcad09bc1de1960c10ec0ee3285aa2dc35bc42d8b206ddfe119b621ff709b9861e00dff5f5caf92d33c79082c90e3e9a811cfb225ccf802c6c51e0dd1ffc5d73e22eecdb9be76ac089ac3cbe39613b2e6f4948ae91a42c6ccbe9f278c01e611cb037785788834d4b7306a5f94e0f3bc26e9731c53db35e41fd2b41ea68bb1a63e21995c245b20761bb235c4bdb5248afed40f7531fff2a4e300c80ad0019f2ee27ac9ab8181f077b7a0bebcaf59459cac8ff3758a91b051e89dee24ec65c2bd9503a6ec590079fb13870f775c5a56325c5317a88e5c439303808c0846b44c4526e81fd78c7cc680ed2993cbf600b108e88aeae1e772b0b0f8ae5806f883cebfb726b4263916b6969cac42ca7a9e5910be070fb64d007d0a7315d91daaf0e62bb35b5e24c1e2a5095a294afe753fd690a0f4bf298d5f1d0e3fb5311399d876cf50e48fb817b3e8c7146c1d061f07f7d0710e182991462d793227590788cd56236e23963e9a41d9b6fee0eca464fe0b5ecc58b78151f57622a97ca700863f02eb1bc9d78d1082feb4f383d1e2eb5bdcfb4fd72020922208eb19f7e809e9e7b184a15bfa5a0a43863b5de3e191059cb78bf74c53bff6104e6c5637ad0121186bf2df31b19bf8e87fc74d1c71d8d520f181c275958a409dcb7bac15021cc57260697c1b3bf9c2db1a1e87f6db39677caf5445f6e85853823a0d358472092cd19d6850a62402d1e425a2d7c0fdb61d2e02f86928c3fbc56d2ff048147b07b2e6dd21224c6bfed79c76e49a5d79a1da6722776e2c4cacf6a71f4fdf8c3421001e4747173ea80422461affd27e3af8ce9fe9eafe6bd76e47ca4bfb9f54e01787798b5ebc4cf20038ab846044605785202d2ebedc82441c938599daa982200676dab42c70099280328e8899465ad1cf74bbc27cefdbabdabe85be02dcc6be2780dce9f7f6b97c77bf7284dc71ce4fdf48f13b36553b372bde71f04c1010f719c9e06ad95bf42e16fb4c5e9f5779cecc8a99830b62e6452cd80f8843dae91517bca2479d53cf305a9d43105eef240fcf12a391e92c49596770405de304801d27b4f39ddf78d44201072df5a66c3753d6cc740f42fca640ec8a9c2aa509941c2d8a8d9dda693b87dc33c5b641332770cdeff855b01b7d48304376e48925c963036bce8d831d7efd5f879447cb403c7e4d7b01c62e0ded5dbd39ccdbb545c5f30bdff5b42ced0c62cd22918e3598f7a6cb7c9cbdb7cc8cce49be5fb57fedbf702e06430500eb0bc6b794b6172145c3d7e0b18e36f98f98861f8dcd0511b707b91dd03caac365db1699acc849db995026ffed7dedce3505260acbf7c4b09aca9d0b09ef40ff6a704425e1195ffcccffca50ddb4c9cd440fe5d8f918774b2852b7177d38c0a40a9325dae46f5c11c30c0b4043067451cd714925e0799f22524d0d0c2997d8d76af181579491ae7893f4d087b1daaf0a5e38723690b34d70a1d0d32b0eff8e2c99c5e155e65f42c60d0fbcc7604b757896e0910f97a1f49f6283ee2e09e4434f0300af0e0abf8b98762f5c6295427fe8e0fb6748b7e7aafa26b02b1d819b307c1f70a1a3ab3812f41571c1b85dbe9603288f4afce9591e8449d99a0c07aa3eb97c33a646725cb03d52fc53ba19064ce10ae7544921f23c2eddae110359572c3d7b81433fcb47a8ed65977667fdbe70a029dd1f9ce9dfa4db220f8a2bb209257dd8d49b864ae9621cd32e3772d453207bdc88ea8be26869afcb5a3c114c5ed52c900da7ed5489e6e199c7ff224a18275897d832bfe121afc7d663750613d5ad6f4ca266eaf1f69c6e0f1617c647e6a5830ceeb3f4d5a2e70730fffd259aed34a0a6d955f29fbbbb96a7051a9b8aeb3de2c077dd632f0f91ae4d2fcc13ad02527dcaac974cd68ce11d09ee138b586a61ea77db1f4d8877146da47b710d5e19796318dca7b99638e5450448ed4b0776331585b6846d0b3f504854665421ba13580166db9ba74f35923efc566aca7d76e32ed30283f7c5b96a12a4cba7130476d1a3b19df10ba213cf604761861d3b4264b342a68811bcaf6c26c4ded5189b15e6f0deafa36e7396871fc0054270765d9cd75681bda91ef8f1f156f51528c7e724218c156417cabe8378dc773cd875b748baaa0360dcfec3f8b5fd79fa15758af830260018537aabe640e55fe9e8d3ba07fd4e849035112962edc1ff6d26a4bfa0e267a938b358a6d95d86a3208e3a1ac448dd043cbae10f847b76a8a20ce0a559bd0f3cba36be6fb50512452bf06915094f7a7c7b1a7a517c7fe3a666249c3368fc161a3932f2d10cd88276932d3d2315ec9bbd8a1511216be52be76d1cc48820c98e773afc3e24181c2666fe05cf22c763103498316ba0759750d575156016a55d457f3a538a4822d1f4dc598d9c9e25fbb0381f2aee56bad06d5c6a1430f3a6fd2b33477e72b8f91a066301dec27e6c9bb69acb1fe54f692ff9b20e14a2a71e577f1f5f7064bef074b0654239599257dc86b12bdec3376250f97f5f005ae534014c6a69ff11c135d18b4dd33c13e4cc11018b7445104b16e6d94b580049efe999a49bc660ce9f8757ea3456c42319d1f91e21277ede209bcb9bf2da1aa875a2c36bff51aeff4e2c01151a0243d5551e016b5e1ef76d8a98443d304604391d823e2248de66f8a0348170e55f5b635d380ccfac02b8fc88df515c0ddf26c4c9d9b7980a35b819aced7c720ebe1fa773e33e84c79dad6f46d3f9bc35e92d2c337a767350d906769ef475cb72fe2e03ecc358f1ee1074f5d620b36480f21255cf596afae8506f5a7b164314cfd890f45fadb279bcb742345ddd9007b4492bde23b40195702ec4cf12305ef29d751e1a31c1fbd3ffd9d29fff53a3dfb371227c0f79f3487ce0e76d7188070768a8ca64021d32ce22f13989dee1c46be72b0d2faacc65a02532940e3759cfd742171bf642d8ad3321c96fb7a6da32a70300226f637fe241477c36bbcf1c01a059b520194003c1f6bb6983d74395fa5b48f914801b01405c4d89b666b6918ca546afcce05aa80dcc4da69af0bfddf2a5460e", "public_inputs_hex": "0x2138b0022ab9af3c96b082bbf307bc9e79f8f1401462e3ac1cb3a9913a5b856c18c40bec999a837ec1f06dcee05102acdef50c501e771cef739dfd0a4cac5e9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000211521e0a601b59f0fa9d199e9f861874db5d701a0c38f6d725d9fd8c1f0b53da03219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218625eaefc46d4dc1d14d29441b83268d90e246af546b51272b038fd206edb2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7296995105557a58df75d3a42759d29e124a15ef43bad6b7fd6a9d93d4efda1c900382d23bccbad9ba827179293d23b719de8374589fcad5bc6d2148bc787593a" }, "decryption_aggregator": { - "proof_hex": "0x00000000000000000000000000000000000000000000000294fc7a9da860e0de000000000000000000000000000000000000000000000009cdced94988b65ecf000000000000000000000000000000000000000000000004d00a28a82c32ce5d0000000000000000000000000000000000000000000000000001fad828e01b9700000000000000000000000000000000000000000000000c0ac27ebaf1221bc80000000000000000000000000000000000000000000000033e0eafab14cbec0d00000000000000000000000000000000000000000000000757cdd9da30a89f350000000000000000000000000000000000000000000000000000205d55489f97000000000000000000000000000000000000000000000007def0d56effcfcc6c000000000000000000000000000000000000000000000000d838d03424697d260000000000000000000000000000000000000000000000055b7cae97a5e905a70000000000000000000000000000000000000000000000000002d8175302221e000000000000000000000000000000000000000000000002d7bc900bcb74da7f00000000000000000000000000000000000000000000000b8c40c16d00c8a23a0000000000000000000000000000000000000000000000013e601e60b676ff950000000000000000000000000000000000000000000000000000d0468cc026ee2459e202e853593058b1db0784b0ed9b36eaf47ee9cadaa08014bf4d8cd3185a2f2fe48532a9a418b29e10b078d3695ba07dd25f5e725ab90220be9ec08687951f316bc8c628606f4298833fd7f9d2c87ea17d01b5fec6bc88ff5919e022391427f7da7bfb75bd26d4480f07dd2369b222049599bf23e227c74018706718915e1e3c8e290aea2380d2f1f59432320fda6a7528328dc891506ea8c73c0877633a237ae8e7ecd4af3e7214f4148072a8b265521d50206cc2e044ea74aae7a67d1d2ddf31fa3c5c4df22481e54e28ede606388e074f21dfdfebe4236a36d36636f3158452502158f58655a3c809c0ae7ae640f43eefc892187fecee43c03179178f04ad773d57f57b4a1b19b4b5c362f5bbd0756fe0fb35313d65e4a6f3c2bbe6842ae28f45b8db241520425f0ec601491d05902e4ce8bdea9afad1f6e468bb39eb2cda34d97fce91c8aca86243f88b865375f479831ca9bb80e8a763469dedbdf92ebbe029e22053d8a32a6d42d9f14cf1d52b663c7fb344f9310eab3d996d6878174a1ff66145793f5a9a9ebd7a951717898cad749fcc7a3006bde824edea17682b37e47270a2bed20f65231a78178a844ef051047364e82a31adad5516137234247998035db34978941f97a592a64654e078b5acfeaf9f5e320d0f18e51c25531c32c6c557ad2f11ffbddd2ea82e89f58d036bae5c5e63e56bfcc1effa99e9d81056314e8ebaa1a4aad6f150638427e469d50ec5435e444f96e5a4f69f34ae42217aeb8185218b67e17ce9681eb4e3a675b2f2f5b4f0f15c7b906561ed7fa55810f2a840ef501bfbadca630161525a3f54b774d877dc386d9fdbc10e2c95a83d18a0cf0c5731d507ec4e5f0f867126444e5c9510794038b3d3d8831f09d55af50394621bc1804b8b4583f3639687613e55138bdb626de365f69aede7048165fe23ca346dda0c5133017abf93d261f82c83099c2c33a8815fe4f092e2ef49fbf5251702d2b6ba4cc3b0f675e38bffc71ba88cc9838a207f844154272c69b01f502d672bcae5907e22252e8262ba05b4f5b7b1f706690f28650fd56e8572d8c7220d132fade6944cf98739494d36ac2e372e7f1d5a4a4e7b8256907b9472fa788b153d4f292fc4ad888ac658e37ad6e85dbd13125f36ba6cfbcfa9dbcf8e4361a5025de0a5ad4ab5c598f2697c534de6914c1ab8f9751d5d7b2ae666e5a65576c5224a88599738d6ed38469061203d645ff172ddde1638f08da2a3bf320edacfcd22b780255c9857273284701d0403376ff3260c92eb9e7273020f6473712248bf1c43a07dab1d32fcea48bb38a41f1656b5ec6a2c6f9670de2f1b60d32e9d7b7227c52778ce41c42652ab58a56904946766edd2eb19417653ebbf939af4dcfbb7163359c46e9022063746940d4d7fd8fb0a62f0826f29898f68cb38d7a0177a5e21cbfc8e122a0af6557c749be7e61939da64b69c7e18000df1cb10977b08a1fa1328ec0746fe2e2142da4e6f9f279e3962a4d80151da3b2c963d7007fa7830230e24dd7805f5ee35897f14f267cfef072a2a7d4d232141c32f7688e2bc12ac982eb506295afabc4d912d6fdcd7c96293c432c3d544bab31a760021260d3edd501b2aad6f77daecb13cbede2301d0fbdd0d3b3bc5c50999fe8fc82af9423c4d9c1a825c8cf5b9b204f4e3d1f2a831fb7cdd33a69cd3afb68ab16a16c3a6c9643f1a408c9e6f64e50245cde76c4aafd47db8ac2f5bfa0cc8f4bd69e082b66e5d380800d387ba9c41fc32f3bcfebc1ffdef85c488e25104c3c8112540af09d0112c2e6c8aa2dd27874d7774b1ea21dd1b54f3c1f9fdced53535104aa0bfbbe49c310a9880d9e7cdc46d6b7bf4609ed6aea3434e450a3fb8be09a879e60e587479dc053dcc5798759ab8f96da932d1eb7cbfa4adf192f00dd167aee524e3329fdc4213d648dc03c02d6a9151ea566a0cda04b59b92b21f0053b15511b6378fec2feb119eea1ad6aec36c068dd52f773c1656b9794c65a7f723a3938dd4977c1c0d3603e745aab6b902d46834b2820f071764b6574fcb80db1c9f13b73cfb6e4b292b2ba0b64a160151353d27c938e2b4b18c5c9ee97e23a3c9a876fe744bcee41fc225a91e7ebf32670753e3ded6e2e9af3425ad3e35e87975ca2c63b2f6186d199b19cee0b57652f3801788cb5f9ad4778acebe7b9fdeda43db9c043ef4137a5b011e592540eef6d70d70e20021d5eec3ba03672e8dede78072d065ececfa35a733198aaac4cd5d63428f39a8e5e21bbf16c50e7e6557c8aec4e0da20a36bf60720056de3908e28cf7581d48db03874f6f6916afe7d0cd3309d4a52328ee74613ca0abbd999c965bc5919e393e49b00467275c648d3ae08d8a95ae793364703219e0bdcc6722159598711d8523ed03e9297bbb79aa6547dba65eb4c35da53adadfb246b58d195676d5b197da5345ecd3c9d523933fa372d1bdfc7b0e3f32d9b00b005f722e8459660830d6526efff66167c6912c7cc6cdbf9efbe76be95246b5a571d8f4c85b490b83f320d3b1dee211a8df62129ece02a51e15a85ca6fb9cf575f24b4cd1b404495341040be48b09a293de2a47fb3b96fae5e6404d0fa80ab4752007b1ee2455f3cfe81f8a0196925fa9fce41611fd8db8d24b0727560d9418eef2209e0ca5f5e3c8cec70623831428d3c400767faeb6afd01dd445b040970f61f17a7d3b7d45bc6005b2ba45d69902cb0052c481b8e77714cafbf97de9b1d69a80f0424d92f06c10e3250af1362c162487b277a6684439aa4ad6cdf6a3bf22761231b27fefbfde64c56f987d91ac5cae036699a100e5361f01cbedde2d18c919e24c22e8de03bab49e04dcedc84a3eca8530c23f22f344ad3f97840b9b18a61e42e1adbb61e311527f8cd6011466cae22387754a8347c340c4cf1cd4d3daa44630cc342d855ba56fd02dd12ebd4beac7623f4d8423eb3abaddf087abfc4287ac01018611b6d426257d5658cf92248dd0519b0097f1ffdf13d114e1a6402b4ecf91f4a331ca61974ddc19623097bc0fbe6f8c015d41874fdd46c4709779832b9a21659c619dd72d147107def203ece56450a8cb78076083d47dc6d5581c0e4261720106c2d002246ad9edbf060db3a529aa65d95e41286165f54e341de6619286f11071ac18276fe5e98e6097b42d4a45bcbe496f88bb6172c031f6432f07bdaf8291b40a45182a9ac24da29515f13705d518802bbc5885395dd9233d953e9bb9d290d91ef07cec9a3de38045ad99a1b7828791ff35660ce77a8848dd1180b472b00856c9b76a8e7fdc5653efaad0154b023f8d930877c53860e3afdb8985a8d2825c2656baf2fc91e8a295b7fe091742c01a3c9fdf5593e74bca97434ec6cd1531edf169b86a01057d936d55f95b3571701aea73150654ce6cae2f98fe198f9832cf05c7c4b579f63985db2581fc7af7ada21d1a6ecc2534ee77b71a9453f7acc017982bac86cab3a4520948f894551800e6745ac5397bd3af021c2ca9e9e7d4501491d40f0262528ce14e591506761ec1f1b04a4b8218dc7240de57c9424124908ff18ea7907906defc1dd158413cdb5e6caeef68b945cefb0c594e236747a1b1dec6fb2c44d7c5ce2a82dd61dde2f33b5a68855602173bc1fb3db2f2a81ed91298d4736329e140e147493320209d367b33e0a638c7827aa2aad48ed8273c3bc0519bd5e4e1a9f986e905ec2a1caa2903929fd4ed46bc7969757a46360005c122e0acde7ee62766d37ae8a5f2e4b547e89dfaa316652ee28ebee61ed6e956fdf052a556d5531ce1e88c4b764707f385139275e389f61e5f89b98c662e5ce990c10b491a61a4e90b0fa60a4441b855471136454e47ecd23d896c6bdd5f09e718703bb8022f7d8647ed9c8156e253458c01648f194c62af28fa76002d10ee418d403203985ec4066a71034667f395f24150e2ad69ccd6231fa3130eafa0670651e0cfcbcec847b040514e9e552d05b09dcc1eadd6193374d776b475d446b1cb961024cd1f3ee9bbf2fc7ade6a6923c1f3f77ee63afa7b1dbf88e0f26f72973cf411f0912f87f18d688280040c40934cfac69db7b0bc9e2dadfbceeceb5d68101e62c279edf9488d4e212ff015caf57d42687fac2e10906637225f287cd50f755d628b5c33d276e3a54de8d8a0a187cf0d41c3ecdbdff4db32162535b35eaa14e592e022ff231c63501d7f23f49b905a607abe8fafa9652522145449f412981d4d60a9055cab29ead09f89003ac2c1c78ed5ed99adc0012318dcfe8d735884ad5df0874c62cc3404cd9e8b614d30b0145e71c58b665c0d2fdcd725c862a6e39ebae0b08331739e0c419afb6f8bd91eaa526cea65f02ee0d5e5a6356c7f43f3ebf932f159efd7d59300dee06c8bbbc756d846f609ca0770eb0402564c490a9d350ba11bd5e5b2e464e2f8d5e7943c93e84784e750178f3ad7fe184aac2bde41f03d2021b45a3bec599ad5cae13e571aac7d3bcc64bb1270f8115e6dffa26c202ab6527535fbd96e3ee327f312ed59b386467002e4b4f45c4b2ac2047e7962b3c8be217298a2626541552599b72662f0569a7dd07facb14d6d5549ac8c731ed8082972ce63108b948327d33e991f9ba410608e8554f2a7490a6bdf46af259bdd695082df8718872508971841634faeb9895de0d4491f3e2017206c97f319a8c0a6e4d1c85cad433989c91a01bae57ccf6ec8940a99850e661caadae51988730fc385229bcad6ce7b97a0eadbd48406b5fbd2997e41ddc2a79ee8224037a36b7cce175218c1c06fb11cd4d271d994ea75a6c4b317b1ae0992df5f55183de4697818f6b13f27ed893be4494f3e90291d27f19f89d80eadcf8dea2145bcbab08b546c8ba194c6cf80a97d4cefdbe79aa1215d6657894192b0216324d652e1d21e124a64821d4ab31faea2074e75791fc017f84acd450c86dff047264915bcc896c3c543c2edd149ade794ade1f7994d6316eddc373e183d6067d51b72d228ebd6887162b04758b45e2b15631a42421c06cf2775240ffcc351f9daf0b357be8bf7afabc2b1e93f729161a1e166ecf00b2623ce8fb94ef53bc8a96877f34d828e4f033e4362f1e27ee8d03cefef5ab49c44a121687d7c7d245efde0b97cf73bddbbedba45f2ff6bbfc4172d84240c261bc2be4f749bdc75e17e46ccd3675bcbc201c97533b111cf3aaa5e460acb2817cc870eda8cb16ebdf7dc00cce816b3574c4818b78bb1d2cee7efa2f46f9e845492d83a5c02e885f2436ab71ca2a2a224701f583fe6026d2db3b84d0ec601ac908afaff0c85c23c705dd823380cdf0e081247d59b1b60c88fd5a27d6db83584f5b89a34bb35d4c35b96106ef73d15ae819fcb47ec96717e5eaae59cf0c11214006361a744d6ac7a25ab5e77f2f8ffc2fb929f60ca0521d3d5555e8794c7977e5f2c3f82566a0dc3b02fc334a5ece8b07c4dd72baf91f227a153e8a11407b673b099ed5a336d10e1ed0d078377159bba4d50ebd0bcc7516c2eeb310e1cd867bb3e48a009ba73d9e0bfcf4e3f09640cde60b0e5923e6f7096155a3ad2a98eb2b181b6ebdafbd076ced5dc7a3480b10465baea717e6b61f293e914219dce1f1b876a424818aef3c0e7058dae0c5a2d09915e076c2142f1e08cd631d377737ff19299dcf4e7ade54fda78a166267ce8c1094a64d390b8dae2259b6e601cc9d235d2914db51489547d9ca30a8c2a1ee2e731f1028564d14f4056be7c0fe8eb2ffe62a2fb7a5ff145d688ca30a27f5dfa85db0c3aa9a860aba12a1b7d5cfb9689148028b605a95abf982a4c8d4bddfe3af32e5d6f7b26998be18aea5924288152469f17a16a11660b072c5440053e6ff8a5959017dae30c85e13523b6fbc00afdaaf2ff8c1a16583c64e6e1bc4959fa154d322c947d0955aac28a3b1ab3eedec9ee7ed7ce944f7e2f62e2c48c22d5592dcd5ab0222ac56441727ec263df9bbfcf0c98055df596019ec2ea30eee2b704346cd7897b10938666b1c4d23a603ad3668d3a0d7fd8639adcc00c86d35f636323314dc4c2768f64ed126b0a6cee630f96df5285d06b336f819433f242f2cdfed6288a139b06f7cdcbd11d13dfe7fb8178badd5c625b0601f1fc05b82d465ae998675a21a119a67fee024db3198472a84885b5625d99d048f795646ebf141972dfc2ae6b0564fe8ccb7069d921ee3be84673cab69e2b5377767408be6057236e471a0987befc554b25617b1059a8bb91e37c219f3cb58dddc5b5fe6034c30001e70f8348674a57a06372b865e3326ff804d8d31f229710352350b0b723d51d760febfb162c675cf34ab201ee76607ebe71a1b46136f68d568cabb46ea5ebf5affbf919c375d38c697b20b248f0fe7206cddb60b9365cc053a13e2d6586790947ea60bdcdbe4cdbe65fb03053f1ad5ca162d49cf0ff176a41101c959a27cb3202c913a668fb3db3091f40684cc1972ea56baa750ade20ac6489f1d82ccf49ae3f850fc26a91986a46f071c3850f7e561f7e99c197065bf71d303f25383c380ddf55266585210b53d36fa149a217ad688dcf0e8ecccf2fe65ea3fbce0250a65b277ce4ce3cac3cef0b38c1c28e6dfb6715f3c28f38040083be9c37beee26aca1200ae15a34d9490dcc5412c7fb4c25ca64f2c6d07ea3b7a4761af12d0f5e472e2081baef1f882111de6831bbb4805bcb6856144c55d7f239d1438d8e0866135a6ecf5d6ff5bdb392ef4261a24ed4a439cc079330b5cc78e34a0efb3ca6a8ff36756b253befa57238876a02bae552b5d9384dcfa2d2154d8d34fb5e0c3b87220792b9c408ed648dcbbd4aa04ea3a463d76a49e365d7367f6f04956ff2702bad4f9cac463d01b43dcb044cb2631d73967b28f9c9da4444f03556276fef611323387027818cebb63b791b61f0e98d4aa94a4118674aa11a5219f1710a2dc474975ebd3dc436b77ca2c9466411c03502ad4ce5a43e3e84b403e745be5b3fb4e8d3e833dadf73889b1a850e031115577c21a2a947e88e663b32fc89dd3dee7fc04270ec0e98dd7ba416b3109de1981d92f1918ad98deb2a72a1fb76c053b187103874333f579d5949f4d20f1fc0cd9938f737539b95565068f672871631909351fdbbc8e6e3880a07a259fe9111b2510551a619ac11bcd3a7f9c8bcbf57da7d3a39c3c03183b4386c8578ee0711be31df13d599e5f1d1dd6c3279ecdd464ef86e94b15a30eb21f47a60fd3ea9b2fc64ab168b00d7d3a5aa6d35889a614b9913222bb89bb344c6e8fde590b413e2eb668737bd00ad942e02af0ac0f1f8faf0bb6a08cc08ba9c78b2c293e4cc0d62ba094060637baedf137e4d78103aa629ab3328a3b8adcc1b62fd06027c06d68186fd2e04fe594bc699eb568edc8bb90ee3aece987e5b2a2018089b5ab1ca2d619ddbf05569ceb9d23e1f1fbf61690d3d2c9dba88e27d438d84e4bb17cbbe3cd1c10d73d1e563c8bae721678c7b22d9bded93aa4527f2135678dc198d0005c5921a7b48aecfcbd1dc92729f0360c33cc9ad7b581cdceb7b38bb8b9d822bbb04402ec2a6d3a66616c4ff68d09bdcb6c4334089dfdc6d3a63155be13d61023c28c1ca88a25be0977971236b26635533eec64b627ce11518adc43985d69308910220c85bdef91505bba10f99919a6b5a14b66a6a065ec49dc998e15b064ad61c7d527411267826844692b4f19b8f6d7ed2196a25793a9aa1d513ff58e78d98c1343018697653c8c57a4798baa88cf2e7dbb3c8ac5f625fe8b215c8c772b99ed92d11258580d1282842e8b0f4035c42b4aa5f87fe6f03b79ece85188db4167b7fc2c20446bf66291fb855a1d9a39de217892b292f16144567957c879fae867d1e96215f75c2df160eb373272da4d441ace877bcd99e2ba9e917e4eb21da3306461710932e3280d8baa624131c6d7207629aac1dfb7751305c97ebddba4cf32f505e92d1f7f3417d2a7c7e0f2f45d2202ed3678bc7b950c2046d044980fcd96c1988d10841c8df616fa31ff7162f82167410d2e8295324d39e42e3558654898c73a082003305c12c89396909e6197117db6fbdd22ed67683083da843b1ee5c9ab184d2a1d70e72b415010e22b22000e198ffa8fda3d1915b88ea4be61fa078d9935d2162725a2b75375cfc381a35ae2c6cd7f7f37a232ca024c412d62410373d8f3d41f1c246f3f9b262faadbb872c0eb846d8ccf186a4972e040f3c67cd894e8563b253c08448b39eb88cf2795df514fc9fc043a9af9b3fd443b155d1c4cc4a02c1516987105a98fd4030fc588ddb086f85d0ef6192fe60e5ae96c8fd6f689a734651db0ff009896d584482f6fd532192bd37a367f2ea8f14f8e14f4055b5f93e59c07998077b7dc410a221d149ab6fd9d7e2f39e0a0318f7692d6246397f5e28d343054edc207b0a109d96752f1aa2e515bdedbe66b76d9ba686be41ba1b7bafbcb10a55c6d64a7332a53bc5401142f73b7312183a5f26f3758b959139a7dd1c77f190a0c1a62ca634f5d245a22f5259307aca5466dba517143431d319ef0f17c97056e143a60d54b4012c3899063c248faeac331cab5c8d52d2c7ca08543bc969018171f14afd40579e2964b1488cd72db78abbf76c6420c7663fe333988fad74c16d15dff2e0179a13f6482a203c57e0835b1292c7e9407e90cf1c9b6a8e925de2e94b23b556f8dd517ea1cb9dbf5b8e3e7b37a75825189bc2da93d91d0d4fc001afacb8a9aee19407d04d4ee0a87bedc7814600a5b1ca5dd2d9b763c9571158c17792d3977839b67b78237ed371e433ef51746becc410f8c4c8ce8fc75857568304505caa527679e9124d3b950fc34a358d86c71c488e22fef5b9f13ec02333004ede26f66b9dd31ef5478bf9d9f9a279db96d2b2798ffd90b9f88073332de6321f13f498bfa24c7d7d657a3699e8a456467221390188cf127b034dedd88e64d1c595ac1217a335bfb7e1d136f87acae17163dd81997997aeec86c8510f4e6a4293d31fc61e96dc92915917e2a9479b41f1312615015ee6fc99669977f2bf62f0115f6f2fead7ef0fcde3199782d503e25f064d42968698d18cc5faf2dcd4c820b6f4241eb0d8fa2d7f3a67f37b6efec872eba2f121a8ad6fd19790a9e81a1012fed2cb7a51927fb055fa243ebacfd9d34e263270da45a07d17ecdfe9e8dacde119470e3335af87d13c2df1ab37bdfee41ef292875890513bd2d054afe9fba3e2ea0a5004a585eea3a392829bbf9924950e1a8f19c8a89bdec7a4d79123458150a675bd0086bc0e606328e1b2d90db66f5bd09b1d0d25f1c23d35dac4e333daf1dfc2b86593c87d7da7ea5f0fc7b2d8316ca6411bd33db11bb20f4e1e7f722401a281d0ec39ba92fedf74ac289c16c39ba916320b900112763ff4cdef5d37020223e1db498730bdb02c6af8ebcefb5278757ce5d6cb334ff87180a23461738162d3051373c6b97bc861daf86b0e81cbb150838618a31e9555ab7e4131a787e5a0c45a10801285cd1304386aa98dbf01a5414b36e6470c7aba836ef357f59d8550268c93f11cfc514093176f596c163165dd736b0272cc9044bb8015d0c06b63f25294a68ef20c7aec7ae1c8ea269751ce4b07c62cc70d0c10c7b060a8629285c0213aeaf333839e428f8350f838f2cd7a92dadde11833196a80bcb361ac6ace41c636b29633940b14fd309f235c195096780167d3d7f61675799c574ec8f87630cd68f46920207719aa96180053eb7426d74d43b400a9bc9635fec645eca84500853823429707819c2df8104d1a901baaaaa82db848bd9c1364ba031eb3634c71d38ad5910831edd84d4c557b4b08f1867ca289c598ac07557c748ab5feab8b82473dab68251ae7bcd7c5647c6d5304311af4486e62fd323c142fb97da8209002da62d0b9c4e83c955be1f41b00cd156e8b8ad42d8babe671df8fede1ee503232106a8069ec3de80432914f60836d20137ab8fccdd1cd0d517a83881d7730de622b7780ccd4366de12bfec1e8c34b0866c0a09ad91ba0e824ad360d821415f680c0a2befd66f5571e8b41772764d328c7db755693d38f27a22ef31ed4dc8405028d31e01fa2652b98e57f431296888f183f6f5be175647e6dec4639d6db8409f1d8c9c029735249ac3895eed4874b9f44bc2af56ebdb8b0517ecdb69134573881a0fcf9f089997750a924a42a58ee70848297aed999ec8cae01e0817db88060e0571ad7f04ec21db8d1e09168c00ea301b237c67fd8a20f32312e2b08cd8321108faf25ce1c6cbe090d143dc20031b78b474d23d16066ecda03739aebf5679c814569ed46af286d8843a6cc6695a80267812bbb4a65b79e36ed365a6e7f38e3e0be8ffafbbe19fbd0f8d7aa7c6182f34f7a98c09b3c1fca3d8c3045f371b2f67251e1ee8c65847410fdbc8c25a8911556b3120221e42f826aa3f9e5494b645250553a33a5d6dff0d923ca2a72822672bf340c1f2120f0e23bb467241766b42232be23e92fb1908df039216ba35db95711df908ab6485a9bba4d5a87bcc4bd05116fd96d22e85e5d6c4082bbef33f8a9599f096e26d596331432b8c961cf9785b0e387d9989be6bf719b761cde20ca1c281b3a701fe1073b4173e2de4194cf8822ad8b7de42b8a338b81fbddcf7577883879b32a40065ad0e2a185a7d16b27130008b65b216b04481466561823657bcb5b911dc9c2a401909ded3c1ecacb90c9c0a3cbfcb83f3ce16e0824806dbc962fec61364e37a86846ff10f34d56114606c256ccdb004b77daaae2dcca4d0b485e79e85e0498f22d2b796a589fb50c656bf1d3fa8227361343d20567a376fd9bf75788d4c2c62492132e9c8cf8cbe69f451062728b673016f2a3d4eeadf5b45c64d3495b0745742aa9c3d967f2f45a6b4062b87fd9b08573a0cbcc91ab6fc3a1edf2af377640fd7da945d06d25de440b3d8030e1442bd08c23cf8c8751ed57bb44d92693c19a677d1dc4ca5bd1a8c61fb350a9522d45fde3891e1a4e42d65b3cc268bc5fbea6be51cdd625b0288b4854d232b514209b5025fc499f2a2dbf5ca9b4dcfa86adce2c04d67fabdceb651fe00f42722a0efaebeef556a81bd9fcd4dddd0253bbcc4572ad366a826e7809bde043e2655337bac8a5010a8e47cf362239c86eba9fff5f990cfaa3207db96c424ece11284e9c4cfd5ee0ffe0cdc22cb4b0cb4f0497643ee90fa455184a0c5445be0781fd0327a4f99abf01978729a78aac72e6bce4f800b2c161fd520ece0c247e5901f54d65b211f28497ae07bb3b1f9e01954a9f5992b24811a107be00011a26dd0022ec83d890760c7c2ba53b0d1814a97820ebdac057be4844c0adceec2d1b167100cc4b883042951639a04cd145d12421d5a8981445520aead1ba5587f6d84ec05377554914556fbfd22bc791426acb934a1c05b9db714c0f5e89783c25634111b86469c041a12d6c754fd275672ac4fd7fdbc9e08a52fe330be346527bbe81503b2554114aa2257af6b19f503f7b144bfa04f009bcb8775056abe574f87fe130847581f87b3574906829ff45b6261775c4d4cde8a8ec7d1ea9ba4266da0249801f64f47b80cd82f1fffb91355ad5352bc6721be76f85afcc95cea9e915e42751d48df16425f7c64e51cbb16208a865413c00e3edc08e7664a8dd5124fafcc751a8b758727e3949eb6e998b4368e0516ab575221e76701aec8274230c792c222217fbb799ebb55bf323c1701fd082d195822034f84c0e328e9a59d7cdd54c85026d5637123848a858ffb1b15e38a1dd075b3a459825a7a28ff99180ed703d79b1dbb81194e04b890fee7b8e3e83368e2c1fd9c08498533e1659edbb95b95212e216fd62eb14f71753e05ead6589239ed51b459731393dcb773b2237854c41bae1c16cb6c4bb645dfb574de656237a7296ca9878a3673ce8990bf543b9d0c12ac1ede30fe923c6d20be7662a0d0e4a38adaffe36550f397dc134d016d8ff980100502b0f39e4965023b7c3b3af13c715c27eb92f52eb1d1ea03d1c03be14f60ce0fd8e4ac03f939b2ce46c0a01edb02f25ca0c0ea42f9dfe809c092557f31beab22311d06896a390c81ee29d9e04cae3ae900307878f58bbf25126d195e38b426158483c1f1e9ef7c902e4bfd0f9c55eec465849e8528fa93873c49eb507376b12857ca9dc18297fba6ae7a87e869dbc2836eee0d87670f4fa76a4c34bd546a5711807ebe17933f1d48bf83fb802743657e432655587833322156c82a0e81ca7a17c494b8d8caae91918133b56bd5a39b8cf1821639be28d7ae328843567c448919124d83648063edea2c82a4cdc631492d0ff9272c3f48e6d764a37eb46b0fa826c0d89d84dab0329281a30afc436a38501e447f405e2228de9722dadb710ee212f5cd5def856e1620f452f1b1c87c99accaa5a582568ec5bb2312ad3507aae82c9e51477dbd662726c68b2d14ba8471d6ba3a99441a3ea0560cc5263b0f729d11963af53bb44db5f0d58d430a82ace1bf46f353ea9e7773181b2455477b81a324f6910de1a2a5660ea5ed1a2898d690172d9e6f112dba6616af5750ccea74c3170577d594c335a412b11e5d6e6ed68e121b7e9cf290da72b97e1de4f0e5b05e28671d66e16b35293d9661a5ec2399e1b3371617b2f081c3d151a93fd9b2765f05afa3f9c804a47aa1bc5360244e072115dcc757cd089be47f94282f4ea347e417a7a09caa4e7b27f26b077d78574e929c59fa46bbe952386998f4b801b1c3741b97c4ca89df3be88ead778f1c1a6b8acf8d89ade02bd0f4087014038b8c603914119b4f1f2dd85a60ffed60f077e185ee096f503ccdcbbc4f7536c3a40abf942534b3129f2c4d48b1c40cfae6aefc3a1fc4edcde068812c95e4346ec5f3bf792e7e79b33f5069bf3d3a38f9cd0e695cd8d7df15fba8820280e37dae622435f1090c6aff3676f8f9c6835b12db35f1dad19430632bc48190b3820465f381d19c0d25a225d743b98e22f896675ddfac868a84c10de3c08bb879ef68053834b75b209d7d2b5b940f6556b33db43abe2e7dccde728594d43e3b3374cf51d00d55301ce63c7304188ec2d1dffeade768ba841f036195ad0a5e56d6819b5bfc9f1bde1bd6273e3067270b4952db3180d3e11ba1fbc38878b57e866066ebd964a60315021dbd9f8ce7615488bdecf26732a657a97121dc0e71b7a2ae9bec2cb1bacd470d8df4153ccd25314e885be1b61a84af34d7b9c2bbf18f632c81594ccb92671a1f06991ae42cd0efaaa7ce5e8ff8420be51526fabaf3eed5a4bbd76b5936d8ed1a8cae7a2a2a073a113a46f6187225ed841a5892e1c259d2fa85151af18dbcb61157df91a0106871694db8b21d2ca384903fa10969ca1ce6d4a85116d39a0b1a2a9c5098a2d510c6ee15fef9ed61bf1d7d2df7673e2dcc3a37bd4beaf7344e2c0a1f01dd0c6bf05c58d82e33bd1b8e50c9dfe5dfd28381771f840f8547a4ae97205b2e7b0feea00acb07650f886ed10719bfd7526b1bcb47885df11adc720189102366f087659d617efeff715f82c271c6faf35ab3aecf3af58e1f1d507dc6fb2054e65fc26d9ce18da03336cb1225e3fc9a742f9d4dc4d31ba0b38f98fb4c8f189b5383795d0b94489ee507b0910d167ee74c2b9ef6abbd95a63574ebd307140efbae3d59a47cc34233d214c8206769385682b134653792796d0b7bb7c9725019323f9803851b4b82f4408771caf5f32c4d820de1254dade69f986f72ce655104e396cf61b531a17043b1ed61c862c4557295a265c55d928721ea03f26395722746881e318a3247a67d991e5367c5e0d27f763c0c8b9ae98da21533b9349bcb2c866e8d6c2817ee8c289e679e112cdce2630cb4659a661765b53da0f2eba019113fcc5d35042b7733dfa1a0f4f4293edcd7498a59095f0f7dd0f69383ace4e70b94066de05000e457ad0e847480178076c8e11fd59c5cb2f4c4ae18cbc29de0127beb7f7d09e4e70a545860998aa357c0a98a930b17423de09e9bf2c836975a04984aa1b23e15655a38d46be2fbbc7ea8b8e6ee5aef0aff5defc62884455c5d28b85f4141cdd20e88adeccb3036e8231e61f2fb2cdee5b76f36db7b563ac44116e5782215a2dc315b6036a8b5479041bbe9d284febb79238c16152d926176e9079cda4a199aa8e2191127aed01772940f9bde39e9d679279a568acf825c9d872a7e64627d6d4793cdc00c4292c8b22941e40679d3ed7242ed61184f8016f4c91a77fbcaeb64e9e2276530f3ed9c53dd57c6b70c5d532919ef31cfbd6cb58d502f92cc48f7a440dfcb3f752bffd5707cb6732b31d9a2225c0293e7518e0e771a0746565220ad9cfb9f62a650cd9ba4eadf536a24884c0e238a211eee9ff3b18d140bce6ebe903302494ba1111c23946be7cb07285132dac658da9743db03c3b912afe729d887514c0949f5c2c764aec634511f650bec1fe67a065de41196de460f2765a27520f6499e447d1668f5b9600b213d7e145f9aaea45f7e599970200a2a86b06625571ecba20e1d979cfce0f298c775efe7a4be1630b9aa1a6a5f3c6523c4d01ffccb6a01c38123d4cc75ba480e9be9bf46f1a43e2e979b62fa4ef2a1248d16ef5b6b7ae3251de269e4fec94e5e5ed659cb2ff7e3d556ac9a34f391fd2668dec15a3695a958e996ec34b8404e5d145476403e237b3406f120ce57abfd17abc99daf3de2d70c8bdc82e9ee0e4781f3960751f07bf47411e79a1464646d", - "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441156615ed204aa948509f830e7e8756e609e419f8a6f8561fddd9202f8abcba0101cad4adce90c01d548eb5a88e3935668204c5bddb827b618a40626d8bc1281f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000203219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db7000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "proof_hex": "0x00000000000000000000000000000000000000000000000ab6871f5e0c604e230000000000000000000000000000000000000000000000063e0c5faa3697e97800000000000000000000000000000000000000000000000c4edda900b7425ccc0000000000000000000000000000000000000000000000000002befd5183896c000000000000000000000000000000000000000000000004d8f5da040d18947000000000000000000000000000000000000000000000000e372e41542c47b15600000000000000000000000000000000000000000000000eb6fd9729b1572bba00000000000000000000000000000000000000000000000000020aebcd8e4cd90000000000000000000000000000000000000000000000027d1ef6bdc1bdc6fb000000000000000000000000000000000000000000000003b63834a1a171bf2700000000000000000000000000000000000000000000000007d98d752da17665000000000000000000000000000000000000000000000000000218b2af27d6fd000000000000000000000000000000000000000000000005fc5b00c064fff6aa000000000000000000000000000000000000000000000005475acb7f772fc6a300000000000000000000000000000000000000000000000d5eaea21fb7f5474c00000000000000000000000000000000000000000000000000025c5ad7f49b8206f35cbb5b62e5b765b61ee0b49a1f8770bea9d70025c2700523a6cdeffad74e2d17c339a3922f7ef70421fafba18febc1023e82b90cd74104a98902574f6d1c226c706d93043c153de5bf841a134de7656959e544c04017eceb0069aa692b1b09d09bd7a13e5ed5ec3350da8de0eb3d4bbbb261473acd3a03e1f56acf424efe0c6de5bfd3bcd37d09cc02b16d1a369712519dc1e780047008bccad88b1517ab06359968bb78d1f165250eefedd6b57eab508d2953f5240a27b3c8f21fbfafb207bef508a58b51480594683a51f7ea0ab2210a377696def48a79ff7efbaa8e0823f41ad197d6b1ee7ee556998280123ec1b9aaae6dd280edf895997e038d1c1c25a9dc3e528367cd6ddf78257f8f4a4c8c13a20283316c3eb5d11cb539b99e5806618d8b39dba1be4c13bd33f165d43ef169b3b372eea8224a06ae43caa0d921207c4f8a36cdc97347efe815d7f3321ce22eb52b6258a38b98f20205e737b6f61ec9e8a86e5cb149f99b66f85d8a15b805fb61123bb0b5dec773cb3b297fe0ee07c1cdbd49dbcb2961b3969e1607c7518a382930487888e32d9bed12a4b7298a26da1f07cba3368953cf9f4a5c127d3fb11a2477adfeebc6be03f27dde2c51742d449697cacf031c884d94c35016ade6bbffa6a1ded069664af9617665c4ed7f09333f51d61f47a9365621869531df3ff6fdde13d7571858c89dad97081a5d032db062ed586adde96838ac6e2c39cb5d50c316062bf90f0b49fa7acd55e6ba1620d7097883c0c1432d691f8ff8fcd8c8075c631e9d6268bed9ca37f2e49bdcf215c9022b55733861a9e7bb732ad6df58cfd3446e7ec2067b2746836af4f7f89c06f25e697f3401aa322174f68a210066a5b63035baed84e1406dc44ec30e74d91129f27facb96b2eb96dbda62db646bbfaa784d1a5fba7dba608196df258f5020c01e07ebef101e89b91d5dec206ff84318ba1638547fe25aec6b87d674308840cae64a836af4ef9ea8cd2ab455927f23633e086b6f6b741485e76bef2b6cc032bb4e67d1a535f5a810fd3cc9899368676a27a90f311557be62e196f20ff52ef13f86ea9ba08fa7eaabb18c6b1afbb4f7771d605e4b1f2be6fe991394d0e2f0626490f444e9ea9fbd75efdb2a25d56667fae74512e2fc0acbd49afee2b2c23e72373c15067632bf4180a0cdc54e9c9394e7154b900a48eba42ba1f44b1d9fc72128f4b3bedaecb9e70e27ed92a46717fb202dac7e349a24736229c5c0836ea091cf2028b1a7eaa6a876513fa071249ea34cd4e1e27e33cd996b948907ebc60990d5930a69598cdf690b2c2c4a1ae184affe235d854ec81da06447e2738270b582081a0574605536f0f836c368de05a08b39fd2d65450c5c5d6d6cf1d87a7cd5a0a079aead0c9239382526011399682aca59d1ac68ee5c18aa4c3f61d13d2dc9f1940bbfceb517ddbe3d02b950661d24e7ed55d0550eb3689f421b3a2a9056451192059863b2f5bbf2fe06feab1df4d0b2165f90a3dbafeca86e3619716ccf0980bf1fe0721c73d5cfcefd66b41e50aa7eadabdd8c455f2779c3b3398132087261797ac8754b7044232941f4d74818e58ed96ec7f2caaf282f7a531758636d2020f7ad743013efcd97a076ead680b17dd244cb55039f07344e15a1a8e2f38870a29edba2439b0837a103e1a8c00e450006e6b589a654b8ccbefd5de0045c8e21c1545fa845e862ab714a464c0b6e00265beabcbaef383504fcf2c5f80cd7360b10d5c24f04fa84e22c6a8e81696a7d4debd55b2058c64ee4339f7e1acb1c8674f2ba9e03d761ec3bc086bf76ce20afa4cbf8328033c71e096a1b21e3e1bbb980c260b3e581b7f7afe02b1ea39b3b73031d0b96080204bffcbf3a04b43f5365bdb249ae301120746252ac7b763df1d20111dc3827f858fc8b12665c07364f9e6042b8adb4df253af298a3b669077f4aeac1aa8f6cc0b44af53c3c1fa4cc56a075d2857a42d3b05cc24d8e929608bb93e738fd680f4cd8af7e6506808ecef185b2b2ebdc44cb7a9ac2efa142c54b09cd054bda803a047c314060dc259796a51bea1238b6879fdf41ffc4269cbc9859c6220dd57373fadcfcda2548125a04d9447280a0696340db71c34a8cabeaf6636088c0331952ccce04a506c57ad047ad7bb9222907f98f62436ed0491d278b5ed7b273a27601258a9ff54c7ac8d3dbb68cf3f1749e0a4c950d439213e3bf0524945627736e7e8fe7f07029b26979c722849f62eedf78929c852c7bd06c10d5a69015ff5983519c3e0937bc3c825472e519547273409dd5643ecec7d1630979937792e5ed4b7cfaa110c7d87ddb2e600ae1cba2ba7b5464a14183ed799350e4d18c512d14b66266eedafd5d32e1141c543d6db248547031da4097158b87ecb7845a8f659c5c02b9ea2ac6f636f3e3d4015739223049f86005714294ac037d14a7ccdac80e89882751314baa8dda7bcb024504e2e27c6a101a3035ff6ef42b99d56c20c824d839f3d98e3131932867267d947c02bb2270046b020798f033e718352799c0cf9d26c86961efbf43562dc263b9d250e36aaa19d199f1d2789110fa14b42d0cd40a491ba99682f72fa9b301d08528b0cd55651c7fecb9fc18e4a725043f251aa9b69be5d31aaee787dc8771fbf31252a90ad86466fbc0eacd6a4cd0d6b94c53ab9fb4c6398b68c5077d5fda03d7e7a1d60824bd6a0859b7fd17c5e3ea922c212b33b1b36a7c5c060eecdec697ba38c0f968500d89f9543e48accf3511e6d0fbb18f089137a7db279c6abe326dd15532f7ce125605cbd676ab45449b2ac04d190420e48f1c0a029eda9944c2b651f681194348f35c5946265da9ae92238bb49a90f7a05e723b185bf8083ee7448ec9517320c5f10fd917b0375e3c88136b03d916220b42d3ef345c9617873212e1e6d1af9a175a5da49ca79114ab1bd3fa654bb9dd1cb9a287c2278f367cc7ef0e35d064982209f67c25194f6d480bd1af6da9c21e590bf77f8e556bc82b3f36629e51ba0bd9e8e8f2a59d7bbbc20be61ddd3d78efba879719d28c116762ad44f7a1c17212136d31493bc280107ecfc3e7f56a3155e6a8dc95ac459573523c5db8e9726948905e785fae860f81331108d539f7f1b8b4c914936d1a06976787a461aed10fcc5ee13a48ab03e06c2eb6d80964b9faad63932663a5a02cbd28b40f159d3191fed983fd4a451dfc47cf6bc11201e2d2faf3049e8ebfb3c7422ca072136f3294c96e6a0fd7348adc0080aa0cffa5ae817a64bf74e78406e6f12e2ce53b20f24795f8d35edf71c5de2ab175685fab6f9c73dc06620bda26f67208c9774b7e52526e6da846f50a867b53b0c964535f5e52c14958463d58d2417c74b2a25d8012d22f20b89f69d9cafc3744aa9a3435674cc2d23c1e68cce4216211907defcc128f00687ab857061bb9fc3fb5f4d2bc70d8652f2f9cf0808c69135eab8fe2b05192d7577511195d93abab820c9f30795df0b10c7f55de58c03d19139b28f5d90128f7041b76c81e6f1444d47642da90ad4e2903cac9481dd31dec5947d5feb56114e0d1865a7bf262de8132d41340ad3aa5e1938c8692b7d9e6af1633d74a3a21d0b65ee6e74bc543b648cfeb52beb7fc0e500afbeab9bdb8a425e43efc6e0ba03f2678dbb80015852281938260095069eaeb25fcbd581d8ebd64babae79e41d11efceb26339550bbba1e36ecc3c91f71ea9f1cd23c0ca5036758e74edf7858e14ad89c7f9c8f71c3cf32fe11c37f583c932bcef67203e999e45700d3a5816870afe8a87a72d9be4d639fa57feccb778e06dbba738460fd0f511c0ad977dd06206c54e18c4a57066e49e55e207d36107037ccc095ec6fa2feae81aaaa44b88370906d542c020f0d3b0e2d80843567501f13066782c96646ccfbe031283544962216425d07ad1796b75e2e9d402062083da2d671d32e1c34e3647bad0322067911656aa8439e56e08c30a1384877c1a32e69c3440d5a25f687c175239ee6cc75c04d11f5e379d21a7e8b32943f9772db2e168f4f1b7b087ee8b7119fd1f18aec2269e83608b1d071924f9f2dcbbfcd070bab6d7f5a447e3a3da752065677b64921849ccadc866212b4a74dfdfe4b8430bdb74f4a9f17a6a99495f0886b442625f2547a6f4500d0dd6f5416d1f40310b3fb8ca4a72861597ffa93f0f9c8e3955fa2bf139bd084522a6726933ffd9e47077365bcf03a3ee29f99edad41cce14458f0684554a86d665240423b236917bcdb313a210c1946d234dd1fe542e742668fd0d64b6ee71070db72111e430e1f27beaba2482951428015889eaad1482b4c2b3157c8eb633ce89bdb8cc75ec48b40e2c50fc5c46e897efa49a7e4b535b16dba729a619462465eef8f964af5497553815acb5545f74d5d677d2c0c1e339416b9c219e50a898ee88e1fb2f1db566e9696f253d79f68772a0aecc07896d2e49332c0f18fd89635440b49b7a80d33da8557759c2fb146fb125ae93087fc2b6749e6a0726f493c7ea11b9d67a1be2dbf04a50105d2b489c75a2efcad8658fb92521580df1b992af777cb0e3ba2c825243eb0e6bdf3d0a6978d1411104b59a46f0bf720a79728ba37648d5d60c06f92608a4dbf1c99fc3e449de7549a7e50762d0232c2b116994593bf466bb0dee85010662193d8ec2fd8a25ecdb2a7b34f7478aed831b3025e984f0ada44ea0333d2d72380d11ea5c1b5db3d182548eb261b77b13181f48514e3f03784963faaaafe860688661a8bbdce565ead9184b182a9802311d19069af44ad2e08496a94d229f869f5a2830c420d4e1bde78c230d8da4384b220c88dc1324a1b82f54e16647c431dd5011a1421c785e130013cfd882192d72f01374b6f2b7f6011bb2194cb772e337033fd01038f1d77810506f0f93aa4eae822649b30fff4c315bcd99b6cb7bc282d60e8aa24fa71bc754482ab58e0d721c3c2ec839f0f8b1c83585fe7ebc00368d3baa4a381440565216c8d2bd04fb96d32311649b8a7a3ca661a0cf53114a8fb32d33cad95318a6154178abc8c06440e21d22e5c70296141521743a8a37855d70b311927b84716de2f8fc092c91eb3a7a1f221f26aea2f88548f3af4b19fc475bcf49786adfc8d7e7349e1693548f512a221f381f9587f1fd3cf3cd069024a1170feafba8229cebb8923a7ab8fbd856196217b589aa128af06c775f25ed9b3aa9bc23803fa5965ee8b7794206585ab63ebc119c919779bcd9b1e024982c6fb199b1679c9af2da8f200348f68ec3b2a00c0f17a15318a649ae59bada674e3a149bb1d6431461411e2df3e2aa1958b722048b16a07dd414de7958c407c3eb8c760779358ec1e2439b58b8d00378bdd2e9e9450de9e777da0eebf79d558d029019a16d1f8c076fa5294863dda329ececee07020721d000c002b15cc3fd3cbf0f0fbc80d75c1bb53ae1b7a244fa507318c57e4c2d6fafb6038ee34355adf14f0363881911843ba3c655934688976f48ac38ca4e162f5b94463b38687726d27320a2d8c97ff9d8a79e81261babee9852ad0958c210d8ae1fe24253e9229b410ba1f11ab4cad40642dd7c818aff33430752c5f36205ef43d3378c9968b0b16a881404aa643c3d555f84b78446cb9bec133cbc10ad00b9207a883ec2d82bad1051a9c39453d1b63188f2c5c052643e597db86bdd1621806a9ef2c04e8cbd9fdaba392d0fc997cf5a49811bb4c8b68f104ccac280541ac123db803c502457797ba6ef0da3b43641d8406b78f1007c09560d45062a65259bc7636f785729b40176ebd0ca1c6f2ffdb9ef2915602c4a6275ac8fa7cbe71adcd397d6043297be672053abf8339f90c137a367ec7d6a782a51b8285f63721916d859797c32299e9413788fc27175800859f9bfc7d3939d4f6b5cc9777b2f198710723aaa5fb5f57450a5ceb88a674796d19ce70fab58e730240326a016922b06a453d8c9f93c4f6a13bb87c227a297ba159e626f5823114a76cd7b0f39410cc25f0afd48083c62151fbaa1853b27d7a17fa1b9e2fa28a284200bf12a6f5a2f550ca3ccff9b6327e4f7d9983a448cae3e7f9ca4e628df133a58dfe58d741b284a4e0b987dcb8dccd1f21874cd434280feb0e942f8f0e5ad8fed96b73bd26f024f4f697877b9a2164985542d2969f52a5b57c433eea4f07a445aa9e833a37f15dc67773cbb58f86cc70a1b5779b019ad98af907b00c0a1fec4492d26e38cd72085f1cba3e5e9c54abcd00c2108dd54aef936879809260609e0787ae4bea1f618a9df278efdd7f15dfe9247dc384fa4f971588fa356b4e67377e8fb6251408f2b82baac18f833a2875d3bc642a5838432ce511b38005fb7024bc01688ef3f670da2fd6a5794ae972da048893816c19549b73421e0d585751496ed222a7cfbca1d415320f214e7cee462d0689ffc31bd05f4c9a5ea3b1791bce9fcbf374d2d14004ca233a4b174ab409e968d6399606527b624923f381eb8c17b2805dfab7cca280308a2b5af4f1aab2d05e78198ee4536f2deebeafec0eebb33df157fdbbace2e747e434240c5cfe49275180859832b2d69923bf08c0d597d9112eeb73568c91fd8ea19778ae26aa6a872c78c89c957d2518154b689bab59b2ffe5bc04361ae131dd276df1a28b2e06a9df883220bcf76424cf289b94d5bd90056ca2a6828f210f1ff74decbe9a8961ee9c5963876aa8face86ca89e9b038fbc5b1ba5bc962c128107f963cd0d439c4fdb465eb7834c943f21c1f3d46a7f057b75b42aac8c472a5c5521abd8d5913f59e4798f9edd0bbe643ab68d2d5f2d4d7b7dba52dd5c8c01fc9c7bdbc80873c54c494f37b6f6fa4536f37b101a16a7da7ac943fe0f666304c7a6659b382bfb94977ea2f22e244f5224369d6025dabac1e08614146ee2501ddaefc72b74b56f7f72ee8d908bc52a354105655e85edb6dc768a83f3dfc0a317c66db9a34532d5f7356579f0741dacf256f0af84798ee17836c4a40fe4b5cc04c199f7039d38a4bc5bc7f2d99fba60a0fdca779b92f02ad5aaf76f1fdefb091381e6eb635e8634516faf93dc50ee8b484c07b917f28d75a657b00a68ba0b71015191755b4d819437281f7565299d9d5ab193750340c3436c4e1ec8af65c201101a107fb877fdcdbd711cc0e888f6a3918bbab8780e9651d6c8bc29d473a25a263d53cc7805cea42498373014e822341492cb0b5846f3651c4de21d6a02b449249f136615c3fa59efaab74793ee99dea1346e28a861afe2f931757642bd3ea028fac43df603f0eef3eb0387cd88048d715e733dc835545af0a970b030f6bcd40739b526796af9c7636fc1e0023beae25886eb1ec9fb69465f36cb8db0143282114a980ff547ceae0ae0328b0a2ff83894cc7efb1d8d3268e623e20257143ddf1690c3f89ba0cea9077e7448601c66a68816c5d7adb596e9df73a9e7d4f3b5151e8e6dba9f96d00681e644aa6cc33f2c88c76c3f204f9e0f4abe5667921cc5dd0a77e105a39ddd0f53525089e44c33468ab32cf7761380760d7c24966908f7291f3cb7b08e1addf167d9a5eb038f1f433e711c6e67adc478606f09c33400928b09658bcc54c224cdca2dae3dba6278e91f8a416474312cd9325be5c38d7f5d7e07f54faf13c87c1b95c0f7f21f9f879644988df52091918a8fb17defcd05035b2c01c5516e3c3a8cb16dbfc84ebf730cc91c289ae1d9a2247ef46867c4c3f8b214c7e231c7382212bcfd3bdfba84e5befd2d04ead43d97823562f066e832f1f31e830d7e9747675bde52ae766e1b6f1fd1868b78f7acd5e595aea09c9dfadbd42088b2218775b734708929cd68d07da0d0544236991c2b7cf3b1c8a535fc2a741e04a56884e7fec5c8b37e770b9ce037d6d9e5963f682452e8d786a57ea1ca4c11dafb71c383f1751378b133a730dff48da6d638942abb532cbcc712975bb260159681bc8d1480de29c8d1791ececbebef1dd47e7055855bd32ab876af784fad1175e04f583e93f827e3336d431ddf5f2a9347290732acb2c1e70b32aa39a1b61535d18522b8e335ee209aef0c81c3ba6c2902fb07d3d35c978a48c6242a5c0a0e5a2a7ab8189202cad4eef209e352db7c4548e813f6479e5ae2cdb3eaf32b601bf6758cf1a0678a0daf9120dc0fa7c4a30f5602f2ae2cd64d49f6cce7de341603a1e9661d5b7553dd96174da8b0763cb968592477ac917adc4dafb94d89522c29bcb39fadde0390e904c2638779567407ab30dabeb7f8beb0b49947dc9e8fe7291197bd5ebbf948c0326263c7cb67a772e3ffefa7d93deb6fe34c83db575bd913e74272a40222380713812899c64497ddd2f0ffa40bd9435ccd8dcf07812318062d0ce0a9887f24c623352f28434512a3f02497d08f70e2acd92c6f9c7db9c70ce84edc6d0b2e6a85061ecbbb6d524d77900e545869d585f02e66c11c5683262a89acb3a1d01fbc647be2e4ff6850475f86dbbf3a5533cddb04f9f759ed3f8c1a58e6111f8ab44f6eb753ce9b76b08ec2c1ca1e8e4a0b12f2468685e97514f80084f9ec72296c13c390174cb7058a1cb652524e152af41bdd9db80f4b26159d019c5915c863e55429c22b5df53f3c2c708d16dcddf9ca6144b3b12c102f6e4726abcb1e662e072858dd31ebcb6fec808ae3818a0e1529bd7f967ae9e4965f942953dd62008a7880ab0f25d1aba340e932e7ca5cfc654d05efae33677e86e73c1e16c255cadb04bfeb1f46d2a57eda2e9e0125c6a25e611177db2f81b52e4ac6270c29e8222702c6a2590dc3853e75a6dc26aad0dc20e13b71d273946564d9d7258d3a80b86cb1a2b655be37f8b0f78265f6bb866571b384a0792cd7ccd6f9f61514364c60b0d46d272ddf70cc26a62f1132e1edd6f617e815dadc8febd9a74e2e645c1d5c5e21b5c8747ef39578966822fb78829299d4ffe3e411f3d3bd5f092e06ad539341a69ee6302e31511830369f8bf22dd7204099269cf871cc0997191f1a2d248d13fcc11672953d9f5ace68497ee899bfb32b4b7bbeb46047e4ef821402516b83cb78caadfadd9fc6c12a398d99f1b878ec66b515e7483a9a0cbccb083041b2aac57d88f01d6d47b3ae84186a84792b52151c25f6587e21f8e6b07b1c0fc000b43896466542644603e14a650e16686d853e62db267e023569d5469c0809a8d114f1007b7827216e65fafee4b603e959641d11636efd348dbd46ed560624ef25c04f501716ef93cee02aad775bd9ee6919852491f3d29b942372e1882085117390b7aeab2e50367937357f59b9f3a24d1c14cc6497dbc0818fbed5041553c7bc5740d0e9aef2bf62243c1ca12f8567c9d3f39a40110770253767fa7c26a871d60e27b75d9e142b1162a4130343e788148124d712988045ef96d48f8920e88ff5c9f60d09d2f77ba9b403bf6c6d0fc0799048710792a96035c73a3e450c283036736b9628210c2497b080c5abc5372666768ca864d18a6f203fed35cf272622ddb9a3970878f471c80de989f90ebd8cea6120f8bd4c593763bdbc5a98058b8395cb3225c7060bb36acc2d22c0338edaac7d75befe39ac4206479c86fa237ab01ca34b0328eb6699049f29188e92e7354e69dd727f960802fefe99c3d80c097dd8728bf5d5825041d67e5ac9858d748bf30271341377176ee8bca796f60e5c92647f6871a1579155741c7b634c268068d9941eb9acd84569018e4de82811c568bf95b24c04cb3cda2a83b14307e668bb54db1a2569360d0caae00498f91e0494092814900d31c78e68f63f06cb09a782d204a10067a78a04801888f8b707e647e4d114ea7c1e7faba4176bd2977b7c1d0e97d6e3ed976c66930ea8d1ea278f3899dc95fad95147a22de703ff82865da597000525a1bd0656d82a84f5d2255bca0b9bef6038b61f0e92a5ba1395707daa095674120eec99fc8ac392eb5a178588131cc52f9e6d45d766712bb3eaf094693a5af7a4f746175bf7aecd09831d846931480245a862576fd3a006b07b1fd9c2db51db74543e275d9e7cc26f2d27452fd95e45041aaedc81d99067f7567db1fe9759e84b4fb2d1bd93bfefdce805a6cabc48654d9d38ebf014ecc33eab6dfe7fbe12b4007cb490b235982a55a611fdeb14cbd17ae02f6dbddc8b4ab0e8209312dfc80292b4c072401ff7336ce8055b3fba6b7058057342f5e55266f9bf87220d9c9ac9fe0853f3d4f4d019d829195d64b5e10165b80751e8ed7945c9a19a7960580b7f3a9d7a6065ce6a26fd3128a6e7e2d8d168db7ce213fc75b4315145a583fdcab1de9a71a41fda973ff1490721ae0f3ee28441b6a46876cebe7b6d692d551bd2746bef1fd28623c1af91c020c7c80ce66224b03e7b9106196f94b8e0c9b5ed67af49449aa45213b412de6e24c842e747291b84fa0553bd0fae951fdf6e70d9412ef0ba752166a5dcf09ecb079b9de21279373de98b9ca059e22817390f90680d8d338d7e35d0dc81751a500d4bd7104c7cc8e52af19d74caa3d6928ce9b0bca085889fbf59a86959c2dcdb13df2f80658bacae156b7f1f4865db24b07fbb6b27942099f9d61e57ae43c3c723bfd52acc8ffaf4fd9cb1147322dc31f7ec5671c5f0ca5c5155ed6d9f2e2413248241722317c262c5bc54875d886f0d90780674e073c5f7f921a6666e3048cd16d5814372e0236fe69a63a4f7118d7eb75bc4465dd01181c9a197ea72f8307c2841f6397a9baab5a97fb04e109006d8127d604f0b7d6736162c40bd8b1c09221e0922d2139987796499a7fb097c9d0a4671b898532936cccadae32376c93dfb059ad2915af4a690d40a516c72d74ce5d4ab9e752f58873ea88227546e021f701702aac2d40191a410dea52f40a4bb996be8002e1c57413e0dea9914098f8a880a8c387b2e3309533a4c07aa51444956ed8fd2a314017814af55da77e40ff7051641fde9c392981a5e7d779529be3e0be0f6890bf19b24f53ebdbde0faf9d69f10e9fe5c469cd99083a9c572eb19b940f9b0e8094a75fc98a7131f2c923408620f3d931493d5a7f759cc6a21edbe9dbe770a109672574d8bf6aacdd48623e833296a76845bc8dc66f9e0bf4d05b889bee67c4c2852750c30d06903783da6ce172c02a8f8653d8211beecc345dc19b6f7cbcc803d66ae2128ba1ba055f761ca3a1aad5843b15c067428741c224242e5c518ffddc45193b3a5ecc922cb13c0d0a72d4130a3f278c1f463f66423e4710027d0b319048abd0a6fbb66c195b9d1452e2e0c7c0e8374b22294a2129630e2cc3dea0b98c2c13758345954fa86eab6ab710a512893425e0268e10b34ee3e2e6a4fb03040687698c97982e30bc2a8a2b2fd2248da56fa8f2105609a497670832678fbaf89a7935cf26768c2c03f443fcc9012eb0427bcaf487189c20e24956f34d23792ad3f62596d3767ac07ae38f3fd4b11324800ac6e2d023729dd5df77dc4e0cd81d0ba8e10e90a266711e69d577bd406b1e218645fa2552bf747d0d1a87fd66c7644155f6f5cba9115d114d7631cec08770d53cead9762e9eb24399c4f97d98fb3c365d158799be00cccd3d20c3b090b431b0c2f7b7c2ef333ec898e469fa101f1adf6f73815f3b09bbdad8349034f1f90f27a8046dca9070e149c1c23150321e612756a0c2c7942d7e30059be4908050ad08455affab49f27dd02ec5169cd976f4567515baecfbadbe97c382d3f1826774b8c096b6862b740081c523d47bd0b9639994b4ec95ab12845086dd5fd482538707df831ef734170cf55d329490aa2e0e49643922241739793a8c75e7386283a026efc405fe0598677d246226a3ece5958e0d48de439e944a05fc643d0641fff61f83de97b677bf4840a977ef5625bc385b7591755fe89ee851ea5d15ebf2655014e914e878ae7c1f8282c6189ecdcfd5110178786f7faa3b05de46b43cf17e113d1492df5303ceba990b322420dc3220d8d4415f89381df54d5ead445821656c02d97585ac6f793d80d33115e53d6415f05f0c5d90c3d77c3d140226be02a3ee5564c70975456bf79d426c8c33efdf706cd178ac3d687e28e4d2204547d0fd5af73db10f93e0b6c523b4ef081426af896697aad46e292ae0c5fab03ec3d0d8dbfff9127ba2e3c4eb3e7a55d92890674bd6132382df800faf6b8b407cb5e2f34f902cc48285bc99e308f2acf715a3b8f884aa21e144ea9fe2a36eadfba592775d95bfd62c6d71c3089734d67d08cb00dd85d23185796cd641089a93e19b12beac08125be0a38ea27cef99c4cdbeddb4b278caa2fb8d47e2745d5c09e83222c0efa0932bba4cb4546e28667c714e5b2b974eabe47fb29b3f78cd5b43742f101e475b51ad373772e93166104a79b4efb175dac3b442b52b9504c88304419102b169b8bacf4d47e97ab2c69e9f5654f5a0cb6f55d8fea831cb665e93bda050b2ad2bee6223c4f9377be451cb1bb4d7d5445b1eb9b58549ec07694f34940216118b0e8add0f6d3ff6199052ea7668d13954c7caa2fe6af1663263c9a6210ae0b01981a9f0fc8d9d2eeb8d92572ad287146f3bf0c20d23de8d08c40c78dad3d061c8102981be8ed68bd6f3b7bf768c40b86a06b6da762153c82d045133d3976a50aa6637a1eec72f4f886a043ee57a4e6ecf52067f7f1dd512d0829b36989687320fec9da648b374ad4e0247d1fa97700c286b7e1103f696941674e6f3a6f9ad4223aab447b6b691951dcceffdcb30f047653433c4f8a1abeab791b5ac76b18502575e60cd921ee2346e0ede35620fb30907dfbfa218913647ad415c9a48ff09305f729f2bf156c6478011766cb094981c086bab98c384f67a7dc579b811ba5c11f607412b5d8cce667aade35ed4efee23bb261c4f278e09b257d502bc61ae48712daae64de5ae2bb6d679b43fd9669b02023aa3eb4d01d10c4603bed9416d06f16bc522446aa35b063e490767fcc90a7bf197281c5c295c1e0415dc27d1e29df06d659418c6c2d19a198517016a3c76ce82fab8d540e656ec7170093c80446c42bb2ab499e9eeed746759a7814701b945e602522926c49aef0d217ba7f3ec0ac1495c4281a7b4a9e1464ce6c97788d617101c912e7918be268957e80dd37fa1c1daef5d845aae5ae93f3d73e13e95b2f974ec218a863270fb89a30f0a81f70f815e9e11d54842d2997758695e9e919c49ee9568970dd985f95ad792c4de69c602ca2a090660e70cff6f75b308d6b58fd3d41bf6c2e1ab5210914a167f161efb208999866e918d0ac040afd7f314e279aea6a9503c0fe69b94c0596ec7204937c282c824f63fa7641a2732762083c6fd099f8538f33fabde31df0ff298e4d691403845eb37769b4a7e325f7b4b90dc138807c7bf8c94b3308c8131021dbc702ec1b0d2773d0d393b5ee72fb1b8c46bf5a2d96e008f0a27bd052c6ce663df466bc10b34b779436e65c9da5839de588d9356cf64f721915fb81cf1107e5861a4fe51ceb29793e3bfd641066d690ab8a27bcd93604040376f886a2bddf62b99aa21012f03a25b1808210494fbfb7c5a6e98c9b0183db9d9366514708d725bd15d6471c37dd3530ee3ab502f0bfaf4639574de4088216596534660c852c04f73e77270a40fd0514c085057ceb30638d46641a2429e8aeb06b89a01c7a19bb9287955c17d5b7abe02aecf3f5e497b8ce13ff4402e42e044c3d270c04db487f5d00f04a0697b0af7a5e27a2a7c04d5bbd73c3e91e2ba020b861cf43676ed66ec9c18f4129399d25127fd3a40f696bb6dbccf3829d8babd3a13e6aec6f0e6bfa632bb90b26c35be6ad3e9fea820c0327735cc17a5244802c9466dd98739a06bb34e742dd044554adfcdbbe8d300cbc39c983ac1a9222513ebf33bd79f429c47d58beece61dd0536dfb22b4ee0b661069eeadf37d8c1456b05f3e19ee3e058c732c8d1ba62a6a39994da45c80490e4a53575e6a739a01d8817ced669ef6dee1dedb34984b2688cd26b1fd6e4ed748d8dba93b6ee4a21493066c1a10f7fa44f50a02206b342a5e15c483ce678c3f87fa37ae6701c4105ea18957e330b13106f6d62f55dd9e05f880741b3c98407fa02b8b956a0b42279f01abf85630fbbe613129d4a710020602b5ce04f6a3eb5c329dc34aa10af6d222c111845bb6016b2cd69f48e4edde14106fe41edd0cc43ad8800ca68c5aa644bdc46f64654b3fa561e10dc84c4612059e79b06da8e2bfb580c268e0c94f02625b1feac968586930f5fa9daa1d52e2166bc02b21f5b5a51eac5219ca1c42b6f563ed338189e34fa6c3e8d5922ca880062f1a75d8d73e3cce28ccd91097acfac61ce220ced87115497eda778f752709011be2b3aec8c33879c1b7d9f041cfea2e9f10ec121a0887e278396eb143953a261cc5d74697fb31f3b525f2129e9dce7542e906372204e07e6d68f59f2bfb9d194e059fc2816cc7b5faab72efde88c1daafb9dce629acf1bdcf7516b7551a8f0d427ae711881bb9dd56f6ddf46d96644fd2e7bd577830779ac1e706b6dc298e0b89cccbea03d22a857589fe4895f822cd5c5fd1634ffe6ef44b7dca09e57cf30126afd120fbdc1cde39aa695bdce2ca770926968c345e801bac05c163e4bbc4279d02daac4bb1a306be1941d646c5e93050adca4277432645be6a4ff50ddf5805d1070e4775d2d6e006453d6b67e718f8289e49ce80b841212e613e505452a827677548ec16fc965456db4e86d45b4d59be76f01e4ba348015b12e75937bf20", + "public_inputs_hex": "0x1a207628cc6936816ccb62a7b56fdbbf8e975293b677c988644e018fc402e441156615ed204aa948509f830e7e8756e609e419f8a6f8561fddd9202f8abcba0101cad4adce90c01d548eb5a88e3935668204c5bddb827b618a40626d8bc1281f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000203219b289bf708a79fb51b2ca033a711b50507c0a223589ab5e58ca23d94046612cdec838f7f61ac1a22b03689875a641846bd79456adbb7461037044d0f88ca2218aba4df02ce9e79dc47d8caacecb6ace5864e51f2b43f071bd722a7e2728219d950512dcce7ada3f9d302cfa36d3768e83ceee44bf4287f509a003a7a4db70000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" } } } diff --git a/circuits/benchmarks/results_insecure/report.md b/circuits/benchmarks/results_insecure/report.md index 86fb40d6b4..d32a04903f 100644 --- a/circuits/benchmarks/results_insecure/report.md +++ b/circuits/benchmarks/results_insecure/report.md @@ -1,9 +1,9 @@ # Enclave ZK Circuit Benchmarks -**Generated:** 2026-04-29 10:02:54 UTC +**Generated:** 2026-05-18 13:44:31 UTC -**Git Branch:** `feat/benches` -**Git Commit:** `36c01c62b86e2527279842280337f2f4724d2487` +**Git Branch:** `feat/1524` +**Git Commit:** `7df3cad298ea4d0194af1dcea8afc397a7c0540e` **Committee Size:** `H=3`, `N=3`, `T=1` @@ -15,36 +15,36 @@ | Circuit | Constraints | Prove time (s) | Verify time (ms) | Proof size (KB) | | -------------------- | ----------- | -------------- | ---------------- | --------------- | -| 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 | +| C0 | 6847 | 0.12 | 26.98 | 15.88 | +| C1 | 57818 | 0.33 | 25.28 | 15.88 | +| C2a | 142625 | 0.77 | 25.29 | 15.88 | +| C2b | 198355 | 0.83 | 25.44 | 15.88 | +| C3a | 132633 | 0.79 | 26.15 | 15.88 | +| C3b | 132633 | 0.79 | 26.15 | 15.88 | +| C4a | 92515 | 0.49 | 25.59 | 15.88 | +| C4b | 92515 | 0.49 | 25.59 | 15.88 | +| C5 | 151717 | 0.79 | 25.38 | 15.88 | +| user_data_encryption | 53732 | 0.32 | 24.95 | 15.88 | +| C6 | 86927 | 0.50 | 24.76 | 15.88 | +| C7 | 104273 | 0.48 | 26.30 | 15.88 | ### Artifacts | Artifact | Proof size | Public input size | Verify gas | Calldata gas | Total gas | | -------- | ---------- | ----------------- | ---------- | ------------ | --------- | -| Π_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 | +| Π_DKG | 10.69 KB | 0.41 KB | 3037910 | 175424 | 3213334 | +| Π_user | 15.88 KB | 0.12 KB | 2972965 | 170200 | 3143165 | +| Π_dec | 10.69 KB | 3.41 KB | 3549222 | 186764 | 3735986 | ### Role / Phase / Activity | Role | Phase | Activity | Prove time | Proof size | Bandwidth | | --------------- | ----- | -------------------------------- | ---------- | ---------- | --------- | -| Each ciphernode | P1 | one-time DKG participation | 379.38 s | 127.00 KB | 128.19 KB | +| Each ciphernode | P1 | one-time DKG participation | 304.50 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) | 80.31 s | 10.69 KB | 14.09 KB | +| User | P3 | per user input | 0.64 s | 15.88 KB | 16.00 KB | +| Each ciphernode | P4 | per computation output (C6) | 0.50 s | 15.88 KB | 16.00 KB | +| Aggregator | P4 | per computation output (C7+fold) | 79.27 s | 10.69 KB | 14.09 KB | ## Integration test (`test_trbfv_actor`) @@ -53,15 +53,15 @@ | Phase | Duration (s) | | ------------------------------------------- | ------------ | | Starting trbfv actor test | 0.00 | -| Setup completed | 2.98 | -| Committee Setup Completed | 20.25 | +| Setup completed | 3.04 | +| Committee Setup Completed | 20.24 | | Committee Finalization Complete | 0.01 | -| ThresholdShares -> PublicKeyAggregated | 379.38 | -| E3Request -> PublicKeyAggregated | 381.92 | -| Application CT Gen | 0.31 | +| ThresholdShares -> PublicKeyAggregated | 304.50 | +| E3Request -> PublicKeyAggregated | 307.02 | +| Application CT Gen | 0.32 | | Running FHE Application | 0.00 | -| Ciphertext published -> PlaintextAggregated | 80.31 | -| Entire Test | 485.79 | +| Ciphertext published -> PlaintextAggregated | 79.27 | +| Entire Test | 409.92 | ### Thread pool (same process as integration test) @@ -75,26 +75,26 @@ | Name | Avg (s) | Runs | Total (s) | | ----------------------------- | ------- | ---- | --------- | -| CalculateDecryptionKey | 0.11 | 3 | 0.33 | -| CalculateDecryptionShare | 0.61 | 3 | 1.84 | -| CalculateThresholdDecryption | 0.57 | 1 | 0.57 | +| CalculateDecryptionKey | 0.12 | 3 | 0.35 | +| CalculateDecryptionShare | 0.61 | 3 | 1.83 | +| CalculateThresholdDecryption | 0.58 | 1 | 0.58 | | 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 | +| ZkDecryptedSharesAggregation | 8.57 | 1 | 8.57 | +| ZkDecryptionAggregation | 49.05 | 1 | 49.05 | +| ZkDkgAggregation | 20.15 | 1 | 20.15 | +| ZkDkgShareDecryption | 1.50 | 6 | 9.03 | +| ZkNodeDkgFold | 62.89 | 3 | 188.67 | +| ZkPkAggregation | 2.16 | 1 | 2.16 | | 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 +| ZkPkGeneration | 1.33 | 3 | 3.99 | +| ZkShareComputation | 2.69 | 6 | 16.16 | +| ZkShareEncryption | 2.49 | 24 | 59.76 | +| ZkThresholdShareDecryption | 6.05 | 3 | 18.14 | +| ZkVerifyShareDecryptionProofs | 0.10 | 3 | 0.29 | +| ZkVerifyShareProofs | 0.23 | 5 | 1.13 | + +Sum of tracked operation wall time: **381.88 s** (often much larger than end-to-end wall clock because work runs in parallel). ## Raw circuit benchmark JSON (Nargo) diff --git a/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts b/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts index 710d72b43c..610a807d53 100644 --- a/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts +++ b/packages/enclave-contracts/scripts/benchmarkGasFromRaw.ts @@ -7,6 +7,12 @@ import { network } from "hardhat"; import fs from "node:fs"; import path from "node:path"; +import { + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS, + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS, + readVkRecursiveHash, +} from "./utils"; + function findRawJson(rawDir: string, fragment: string): any { const entries = fs.readdirSync(rawDir).filter((f) => f.endsWith(".json")); for (const f of entries) { @@ -92,6 +98,37 @@ async function main() { const dkgPublicInputs = hexToBytes32Array(dkgPublicHex); const decPublicInputs = hexToBytes32Array(decPublicHex); + + const expectedNodesFoldKeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + const expectedC6FoldKeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7KeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + + if ( + dkgPublicInputs[0] !== expectedNodesFoldKeyHash || + dkgPublicInputs[1] !== expectedC5KeyHash + ) { + throw new Error( + "DKG aggregator proof publicInputs[0..1] do not match nodes_fold / pk_aggregation .vk_recursive_hash artifacts", + ); + } + if ( + decPublicInputs[0] !== expectedC6FoldKeyHash || + decPublicInputs[1] !== expectedC7KeyHash + ) { + throw new Error( + "Decryption aggregator proof publicInputs[0..1] do not match c6_fold / decrypted_shares_aggregation .vk_recursive_hash artifacts", + ); + } + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const libFactory = await ethers.getContractFactory( @@ -129,7 +166,7 @@ async function main() { const bfvPk = await ( await ethers.getContractFactory("BfvPkVerifier") - ).deploy(dkgAggAddress, dkgPublicInputs[0], dkgPublicInputs[1]); + ).deploy(dkgAggAddress, expectedNodesFoldKeyHash, expectedC5KeyHash); await bfvPk.waitForDeployment(); const dkgEncodedProof = abiCoder.encode( @@ -137,11 +174,17 @@ async function main() { [dkgProofHex, dkgPublicInputs], ); const pkCommitment = dkgPublicInputs[dkgPublicInputs.length - 1]; + const dkgOk = await bfvPk.verify.staticCall(pkCommitment, dkgEncodedProof); + if (!dkgOk) { + throw new Error( + "BfvPkVerifier.verify returned false for folded DKG proof (Honk VK / proof mismatch?)", + ); + } const dkgGas = await bfvPk.verify.estimateGas(pkCommitment, dkgEncodedProof); const bfvDec = await ( await ethers.getContractFactory("BfvDecryptionVerifier") - ).deploy(decAggAddress, decPublicInputs[0], decPublicInputs[1]); + ).deploy(decAggAddress, expectedC6FoldKeyHash, expectedC7KeyHash); await bfvDec.waitForDeployment(); const decEncodedProof = abiCoder.encode( @@ -149,6 +192,12 @@ async function main() { [decProofHex, decPublicInputs], ); const plaintextHash = plaintextHashFromPublicInputs(decPublicInputs, ethers); + const decOk = await bfvDec.verify.staticCall(plaintextHash, decEncodedProof); + if (!decOk) { + throw new Error( + "BfvDecryptionVerifier.verify returned false for folded decryption proof (Honk VK / proof mismatch?)", + ); + } const decGas = await bfvDec.verify.estimateGas( plaintextHash, decEncodedProof, diff --git a/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts b/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts index ef22900ecf..a7072d6042 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/bfvDecryptionVerifier.ts @@ -11,6 +11,7 @@ import { } from "../../types"; import { BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS, + assertBfvDecryptionVerifierSubCircuitVkHashes, readDeploymentArgs, readVkRecursiveHash, storeDeploymentArgs, @@ -45,6 +46,10 @@ export const deployAndSaveBfvDecryptionVerifier = async ( existing.address, signer, ); + await assertBfvDecryptionVerifierSubCircuitVkHashes( + bfvDecryptionVerifier, + existing.address, + ); return { bfvDecryptionVerifier }; } diff --git a/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts b/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts index d2eaacdb76..b51dd54401 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts @@ -11,6 +11,7 @@ import { } from "../../types"; import { BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS, + assertBfvPkVerifierSubCircuitVkHashes, readDeploymentArgs, readVkRecursiveHash, storeDeploymentArgs, @@ -43,6 +44,10 @@ export const deployAndSaveBfvPkVerifier = async ( existing.address, signer, ); + await assertBfvPkVerifierSubCircuitVkHashes( + bfvPkVerifier, + existing.address, + ); return { bfvPkVerifier }; } diff --git a/packages/enclave-contracts/scripts/utils.ts b/packages/enclave-contracts/scripts/utils.ts index 324ac681b9..bd672365e1 100644 --- a/packages/enclave-contracts/scripts/utils.ts +++ b/packages/enclave-contracts/scripts/utils.ts @@ -60,6 +60,77 @@ export function readVkRecursiveHash(filePath: string): string { return `0x${raw.toString("hex")}`; } +/** On-chain `BfvPkVerifier` sub-circuit VK immutables (for deploy-time staleness checks). */ +export interface BfvPkVerifierVkReader { + expectedNodesFoldKeyHash(): Promise; + expectedC5KeyHash(): Promise; +} + +/** On-chain `BfvDecryptionVerifier` sub-circuit VK immutables (for deploy-time staleness checks). */ +export interface BfvDecryptionVerifierVkReader { + expectedC6FoldKeyHash(): Promise; + expectedC7KeyHash(): Promise; +} + +/** + * Ensures deployed `BfvPkVerifier` immutables match current `*.vk_recursive_hash` artifacts. + * Call when reusing an address from `deployed_contracts.json` after `pnpm compile:circuits`. + */ +export async function assertBfvPkVerifierSubCircuitVkHashes( + verifier: BfvPkVerifierVkReader, + address: string, +): Promise { + const expectedNodesFold = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5 = readVkRecursiveHash(BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5); + const [onChainNodesFold, onChainC5] = await Promise.all([ + verifier.expectedNodesFoldKeyHash(), + verifier.expectedC5KeyHash(), + ]); + + if (onChainNodesFold === expectedNodesFold && onChainC5 === expectedC5) { + return; + } + + throw new Error( + `BfvPkVerifier at ${address} has stale sub-circuit VK immutables. ` + + `On-chain nodes_fold=${onChainNodesFold} expected=${expectedNodesFold}; ` + + `on-chain c5=${onChainC5} expected=${expectedC5}. ` + + `Redeploy after pnpm compile:circuits or remove the stale entry from deployed_contracts.json.`, + ); +} + +/** + * Ensures deployed `BfvDecryptionVerifier` immutables match current `*.vk_recursive_hash` artifacts. + */ +export async function assertBfvDecryptionVerifierSubCircuitVkHashes( + verifier: BfvDecryptionVerifierVkReader, + address: string, +): Promise { + const expectedC6Fold = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7 = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + const [onChainC6Fold, onChainC7] = await Promise.all([ + verifier.expectedC6FoldKeyHash(), + verifier.expectedC7KeyHash(), + ]); + + if (onChainC6Fold === expectedC6Fold && onChainC7 === expectedC7) { + return; + } + + throw new Error( + `BfvDecryptionVerifier at ${address} has stale sub-circuit VK immutables. ` + + `On-chain c6_fold=${onChainC6Fold} expected=${expectedC6Fold}; ` + + `on-chain c7=${onChainC7} expected=${expectedC7}. ` + + `Redeploy after pnpm compile:circuits or remove the stale entry from deployed_contracts.json.`, + ); +} + // Type for deployment arguments export interface DeploymentArgs { address: string; diff --git a/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts b/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts new file mode 100644 index 0000000000..d084be989f --- /dev/null +++ b/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import { expect } from "chai"; +import { network } from "hardhat"; +import fs from "node:fs"; +import path from "node:path"; + +import { + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS, + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS, + REPO_ROOT, + assertBfvDecryptionVerifierSubCircuitVkHashes, + assertBfvPkVerifierSubCircuitVkHashes, + readVkRecursiveHash, +} from "../scripts/utils"; +import type { BfvDecryptionVerifier, BfvPkVerifier } from "../types"; + +const { ethers, networkHelpers } = await network.connect(); +const { loadFixture } = networkHelpers; + +const INTEGRATION_SUMMARY = path.join( + REPO_ROOT, + "circuits/benchmarks/results_insecure/integration_summary.json", +); + +const vkArtifactsPresent = (): boolean => + Object.values(BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS).every((p) => + fs.existsSync(p), + ) && + Object.values(BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS).every((p) => + fs.existsSync(p), + ); + +function hexToBytes32Array(hex: string): string[] { + const clean = hex.startsWith("0x") ? hex.slice(2) : hex; + const out: string[] = []; + for (let i = 0; i < clean.length; i += 64) { + out.push(`0x${clean.slice(i, i + 64)}`); + } + return out; +} + +function plaintextHashFromPublicInputs(publicInputs: string[]): string { + const messageCoeffsCount = 100; + const offset = publicInputs.length - messageCoeffsCount; + const plaintext = new Uint8Array(messageCoeffsCount * 8); + for (let i = 0; i < messageCoeffsCount; i++) { + const coeff = BigInt(publicInputs[offset + i]); + for (let j = 0; j < 8; j++) { + plaintext[i * 8 + j] = Number((coeff >> BigInt(j * 8)) & 0xffn); + } + } + return ethers.keccak256(plaintext); +} + +describe("BfvVkBindingIntegration", function () { + const deployHonkAndBfv = async () => { + const libFactory = await ethers.getContractFactory( + "contracts/verifiers/bfv/honk/DkgAggregatorVerifier.sol:ZKTranscriptLib", + ); + const zkTranscriptLib = await libFactory.deploy(); + await zkTranscriptLib.waitForDeployment(); + const zkTranscriptLibAddress = await zkTranscriptLib.getAddress(); + + const dkgAggFactory = await ethers.getContractFactory( + "DkgAggregatorVerifier", + { + libraries: { + "project/contracts/verifiers/bfv/honk/DkgAggregatorVerifier.sol:ZKTranscriptLib": + zkTranscriptLibAddress, + }, + }, + ); + const dkgAgg = await dkgAggFactory.deploy(); + await dkgAgg.waitForDeployment(); + + const decAggFactory = await ethers.getContractFactory( + "DecryptionAggregatorVerifier", + { + libraries: { + "project/contracts/verifiers/bfv/honk/DecryptionAggregatorVerifier.sol:ZKTranscriptLib": + zkTranscriptLibAddress, + }, + }, + ); + const decAgg = await decAggFactory.deploy(); + await decAgg.waitForDeployment(); + + const expectedNodesFoldKeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + const expectedC6FoldKeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7KeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + + const bfvPk = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy( + await dkgAgg.getAddress(), + expectedNodesFoldKeyHash, + expectedC5KeyHash, + ); + await bfvPk.waitForDeployment(); + + const bfvDec = await ( + await ethers.getContractFactory("BfvDecryptionVerifier") + ).deploy( + await decAgg.getAddress(), + expectedC6FoldKeyHash, + expectedC7KeyHash, + ); + await bfvDec.waitForDeployment(); + + return { + bfvPk: bfvPk as unknown as BfvPkVerifier, + bfvDec: bfvDec as unknown as BfvDecryptionVerifier, + }; + }; + + describe("deploy-time VK staleness checks", function () { + it("rejects BfvPkVerifier with stale immutables", async function () { + const { bfvPk } = await loadFixture(deployHonkAndBfv); + const address = await bfvPk.getAddress(); + const stale = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy( + await bfvPk.circuitVerifier(), + ethers.id("stale-nodes-fold"), + ethers.id("stale-c5"), + ); + await stale.waitForDeployment(); + + await expect( + assertBfvPkVerifierSubCircuitVkHashes( + stale as unknown as BfvPkVerifier, + await stale.getAddress(), + ), + ).to.be.rejectedWith(/stale sub-circuit VK immutables/); + + await expect(assertBfvPkVerifierSubCircuitVkHashes(bfvPk, address)).to.not + .be.rejected; + }); + + it("rejects BfvDecryptionVerifier with stale immutables", async function () { + const { bfvDec } = await loadFixture(deployHonkAndBfv); + const address = await bfvDec.getAddress(); + const stale = await ( + await ethers.getContractFactory("BfvDecryptionVerifier") + ).deploy( + await bfvDec.circuitVerifier(), + ethers.id("stale-c6"), + ethers.id("stale-c7"), + ); + await stale.waitForDeployment(); + + await expect( + assertBfvDecryptionVerifierSubCircuitVkHashes( + stale as unknown as BfvDecryptionVerifier, + await stale.getAddress(), + ), + ).to.be.rejectedWith(/stale sub-circuit VK immutables/); + + await expect( + assertBfvDecryptionVerifierSubCircuitVkHashes(bfvDec, address), + ).to.not.be.rejected; + }); + }); + + const runFoldedProofIntegration = + fs.existsSync(INTEGRATION_SUMMARY) && vkArtifactsPresent(); + + (runFoldedProofIntegration ? it : it.skip)( + "folded aggregator proofs: artifact VK hashes match publicInputs[0..1] and verify passes", + async function () { + this.timeout(120_000); + + const summary = JSON.parse( + fs.readFileSync(INTEGRATION_SUMMARY, "utf8"), + ) as { + folded_artifacts: { + dkg_aggregator: { proof_hex: string; public_inputs_hex: string }; + decryption_aggregator: { + proof_hex: string; + public_inputs_hex: string; + }; + }; + }; + + const dkgPublicInputs = hexToBytes32Array( + summary.folded_artifacts.dkg_aggregator.public_inputs_hex, + ); + const decPublicInputs = hexToBytes32Array( + summary.folded_artifacts.decryption_aggregator.public_inputs_hex, + ); + + const expectedNodesFoldKeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.nodesFold, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + const expectedC6FoldKeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c6Fold, + ); + const expectedC7KeyHash = readVkRecursiveHash( + BFV_DECRYPTION_SUB_CIRCUIT_VK_HASH_PATHS.c7, + ); + + expect(dkgPublicInputs[0]).to.equal(expectedNodesFoldKeyHash); + expect(dkgPublicInputs[1]).to.equal(expectedC5KeyHash); + expect(decPublicInputs[0]).to.equal(expectedC6FoldKeyHash); + expect(decPublicInputs[1]).to.equal(expectedC7KeyHash); + + const { bfvPk, bfvDec } = await deployHonkAndBfv(); + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + + const dkgEncoded = abiCoder.encode( + ["bytes", "bytes32[]"], + [summary.folded_artifacts.dkg_aggregator.proof_hex, dkgPublicInputs], + ); + const pkCommitment = dkgPublicInputs[dkgPublicInputs.length - 1]; + expect(await bfvPk.verify.staticCall(pkCommitment, dkgEncoded)).to.equal( + true, + ); + + const decEncoded = abiCoder.encode( + ["bytes", "bytes32[]"], + [ + summary.folded_artifacts.decryption_aggregator.proof_hex, + decPublicInputs, + ], + ); + const plaintextHash = plaintextHashFromPublicInputs(decPublicInputs); + expect( + await bfvDec.verify.staticCall(plaintextHash, decEncoded), + ).to.equal(true); + }, + ); + + (runFoldedProofIntegration ? it : it.skip)( + "rejects verify when expectedNodesFoldKeyHash is wrong by one byte", + async function () { + this.timeout(120_000); + + const summary = JSON.parse( + fs.readFileSync(INTEGRATION_SUMMARY, "utf8"), + ) as { + folded_artifacts: { + dkg_aggregator: { proof_hex: string; public_inputs_hex: string }; + }; + }; + + const dkgPublicInputs = hexToBytes32Array( + summary.folded_artifacts.dkg_aggregator.public_inputs_hex, + ); + const expectedC5KeyHash = readVkRecursiveHash( + BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS.c5, + ); + + const libFactory = await ethers.getContractFactory( + "contracts/verifiers/bfv/honk/DkgAggregatorVerifier.sol:ZKTranscriptLib", + ); + const zkTranscriptLib = await libFactory.deploy(); + await zkTranscriptLib.waitForDeployment(); + + const dkgAgg = await ( + await ethers.getContractFactory("DkgAggregatorVerifier", { + libraries: { + "project/contracts/verifiers/bfv/honk/DkgAggregatorVerifier.sol:ZKTranscriptLib": + await zkTranscriptLib.getAddress(), + }, + }) + ).deploy(); + await dkgAgg.waitForDeployment(); + + const nodesFoldBuf = Buffer.from(dkgPublicInputs[0].slice(2), "hex"); + nodesFoldBuf[0] ^= 0xff; + const wrongNodesFold = `0x${nodesFoldBuf.toString("hex")}`; + + const bfvPk = await ( + await ethers.getContractFactory("BfvPkVerifier") + ).deploy(await dkgAgg.getAddress(), wrongNodesFold, expectedC5KeyHash); + await bfvPk.waitForDeployment(); + + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + const dkgEncoded = abiCoder.encode( + ["bytes", "bytes32[]"], + [summary.folded_artifacts.dkg_aggregator.proof_hex, dkgPublicInputs], + ); + const pkCommitment = dkgPublicInputs[dkgPublicInputs.length - 1]; + + expect(await bfvPk.verify.staticCall(pkCommitment, dkgEncoded)).to.equal( + false, + ); + }, + ); +}); From 74631321f84c37c9cea8d25ceaf2150896c6524f Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 18 May 2026 15:59:10 +0200 Subject: [PATCH 3/5] address coderabbit comments --- .../verifiers/bfv/BfvDecryptionVerifier.sol | 2 +- .../contracts/verifiers/bfv/BfvPkVerifier.sol | 2 +- .../test/BfvDecryptionVerifier.spec.ts | 6 +++--- .../enclave-contracts/test/BfvPkVerifier.spec.ts | 12 ++++++++++++ .../test/BfvVkBindingIntegration.spec.ts | 10 +++++++--- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol b/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol index 91b7c5c7d3..c572c09498 100644 --- a/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol +++ b/packages/enclave-contracts/contracts/verifiers/bfv/BfvDecryptionVerifier.sol @@ -52,7 +52,7 @@ contract BfvDecryptionVerifier is IDecryptionVerifier { (bytes, bytes32[]) ); - if (publicInputs.length < MESSAGE_COEFFS_COUNT) { + if (publicInputs.length < MESSAGE_COEFFS_COUNT + 2) { return false; } if (publicInputs[0] != expectedC6FoldKeyHash) { diff --git a/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol b/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol index 44c1c11832..de5cb6a700 100644 --- a/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol +++ b/packages/enclave-contracts/contracts/verifiers/bfv/BfvPkVerifier.sol @@ -47,7 +47,7 @@ contract BfvPkVerifier is IPkVerifier { (bytes, bytes32[]) ); - if (publicInputs.length < 2) { + if (publicInputs.length < 3) { return false; } if (publicInputs[0] != expectedNodesFoldKeyHash) { diff --git a/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts b/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts index 32916efde6..d2bc3e29a5 100644 --- a/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts +++ b/packages/enclave-contracts/test/BfvDecryptionVerifier.spec.ts @@ -101,7 +101,7 @@ describe("BfvDecryptionVerifier", function () { ).to.be.revert(ethers); }); - it("returns false when publicInputs.length < MESSAGE_COEFFS_COUNT", async function () { + it("returns false when publicInputs.length < MESSAGE_COEFFS_COUNT + 2", async function () { const { bfvDecryptionVerifier, mockCircuit } = await loadFixture( deployWithMockCircuit, ); @@ -110,8 +110,8 @@ describe("BfvDecryptionVerifier", function () { const messageCoeffs = [1n, 2n, 3n]; const publicInputs = buildPublicInputsWithMessage( messageCoeffs, - 100, - ).slice(0, MESSAGE_COEFFS_COUNT - 1); + MESSAGE_COEFFS_COUNT + 2, + ).slice(0, MESSAGE_COEFFS_COUNT + 1); const plaintextHash = plaintextToHash(messageCoeffs); const proof = encodeProof("0x01", publicInputs); diff --git a/packages/enclave-contracts/test/BfvPkVerifier.spec.ts b/packages/enclave-contracts/test/BfvPkVerifier.spec.ts index 5caf352950..c2d24dbf57 100644 --- a/packages/enclave-contracts/test/BfvPkVerifier.spec.ts +++ b/packages/enclave-contracts/test/BfvPkVerifier.spec.ts @@ -73,6 +73,18 @@ describe("BfvPkVerifier", function () { expect(result).to.equal(false); }); + it("returns false when publicInputs has only vk hashes (no pkCommitment slot)", async function () { + const { bfvPkVerifier } = await loadFixture(deployWithMockCircuit); + const pkCommitment = ethers.keccak256("0xabcd"); + const proof = encodeProof("0x01", [ + EXPECTED_NODES_FOLD_KEY_HASH, + EXPECTED_C5_KEY_HASH, + ]); + + const result = await bfvPkVerifier.verify.staticCall(pkCommitment, proof); + expect(result).to.equal(false); + }); + it("returns false when nodes_fold key hash does not match", async function () { const revertingVerifier = await ( await ethers.getContractFactory("RevertOnVerifyCircuitVerifier") diff --git a/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts b/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts index d084be989f..a437d063fe 100644 --- a/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts +++ b/packages/enclave-contracts/test/BfvVkBindingIntegration.spec.ts @@ -26,7 +26,7 @@ const INTEGRATION_SUMMARY = path.join( "circuits/benchmarks/results_insecure/integration_summary.json", ); -const vkArtifactsPresent = (): boolean => +const hasCompiledVkArtifacts = (): boolean => Object.values(BFV_PK_SUB_CIRCUIT_VK_HASH_PATHS).every((p) => fs.existsSync(p), ) && @@ -34,6 +34,10 @@ const vkArtifactsPresent = (): boolean => fs.existsSync(p), ); +const describeDeployTimeVkChecks = hasCompiledVkArtifacts() + ? describe + : describe.skip; + function hexToBytes32Array(hex: string): string[] { const clean = hex.startsWith("0x") ? hex.slice(2) : hex; const out: string[] = []; @@ -126,7 +130,7 @@ describe("BfvVkBindingIntegration", function () { }; }; - describe("deploy-time VK staleness checks", function () { + describeDeployTimeVkChecks("deploy-time VK staleness checks", function () { it("rejects BfvPkVerifier with stale immutables", async function () { const { bfvPk } = await loadFixture(deployHonkAndBfv); const address = await bfvPk.getAddress(); @@ -176,7 +180,7 @@ describe("BfvVkBindingIntegration", function () { }); const runFoldedProofIntegration = - fs.existsSync(INTEGRATION_SUMMARY) && vkArtifactsPresent(); + fs.existsSync(INTEGRATION_SUMMARY) && hasCompiledVkArtifacts(); (runFoldedProofIntegration ? it : it.skip)( "folded aggregator proofs: artifact VK hashes match publicInputs[0..1] and verify passes", From cc6e3957cd3eadb880a872b2734d87bb64720521 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 18 May 2026 16:33:51 +0200 Subject: [PATCH 4/5] disable for e2e test --- examples/CRISP/enclave.config.yaml | 1 + examples/CRISP/packages/crisp-contracts/deploy/deploy.ts | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/CRISP/enclave.config.yaml b/examples/CRISP/enclave.config.yaml index 0475a5ef33..b0907e2ebf 100644 --- a/examples/CRISP/enclave.config.yaml +++ b/examples/CRISP/enclave.config.yaml @@ -21,6 +21,7 @@ chains: address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" deploy_block: 4 - name: "sepolia" + enabled: false # Public Sepolia WebSocket endpoint (see repo docs for the recommended default). rpc_url: "wss://ethereum-sepolia-rpc.publicnode.com" contracts: diff --git a/examples/CRISP/packages/crisp-contracts/deploy/deploy.ts b/examples/CRISP/packages/crisp-contracts/deploy/deploy.ts index f4236fba13..57f0711fd5 100644 --- a/examples/CRISP/packages/crisp-contracts/deploy/deploy.ts +++ b/examples/CRISP/packages/crisp-contracts/deploy/deploy.ts @@ -33,8 +33,10 @@ export const deploy = async () => { const shouldDeployEnclave = Boolean(process.env.DEPLOY_ENCLAVE) const shouldPrintEnv = Boolean(process.env.PRINT_ENV_VARS) + // Mock BFV verifiers only: CRISP E2E uses E3_PROOF_AGGREGATION_ENABLED=false and does not + // ship compiled `*.vk_recursive_hash` artifacts required by BfvPkVerifier / BfvDecryptionVerifier. if (shouldDeployEnclave) { - await deployEnclave(true, true) + await deployEnclave(true, false) } await deployCRISPContracts() @@ -60,5 +62,6 @@ export const deploy = async () => { } deploy().catch((err) => { - console.log(err) + console.error(err) + process.exit(1) }) From 83a00dc43988949ee303b9bc6422292c15f63ecc Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 18 May 2026 17:04:34 +0200 Subject: [PATCH 5/5] update addresses --- examples/CRISP/enclave.config.yaml | 4 ++-- examples/CRISP/server/.env.example | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/CRISP/enclave.config.yaml b/examples/CRISP/enclave.config.yaml index b0907e2ebf..d5c3c9a26b 100644 --- a/examples/CRISP/enclave.config.yaml +++ b/examples/CRISP/enclave.config.yaml @@ -3,8 +3,8 @@ chains: rpc_url: ws://localhost:8545 contracts: e3_program: - address: "0x809d550fca64d94Bd9F66E60752A544199cfAC3D" - deploy_block: 31 + address: "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF" + deploy_block: 37 enclave: address: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" deploy_block: 14 diff --git a/examples/CRISP/server/.env.example b/examples/CRISP/server/.env.example index e3d3929bfb..5696348a10 100644 --- a/examples/CRISP/server/.env.example +++ b/examples/CRISP/server/.env.example @@ -15,7 +15,7 @@ CRON_API_KEY=1234567890 # Based on Default Anvil Deployments (Only for testing) ENCLAVE_ADDRESS=0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e FEE_TOKEN_ADDRESS=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 -E3_PROGRAM_ADDRESS=0x809d550fca64d94Bd9F66E60752A544199cfAC3D +E3_PROGRAM_ADDRESS=0x0E801D84Fa97b50751Dbf25036d067dCf18858bF CIPHERNODE_REGISTRY_ADDRESS=0xa513E6E4b8f2a923D98304ec87F64353C4D5C853 # E3 Config